home *** CD-ROM | disk | FTP | other *** search
-
- ;┌───────────────────────────────────────────────────────────────────┐
- ;│ │
- ;│ █████ █ █ █████ █ █ █████ │
- ;│ █ ██ ██ █ █ █ █ │
- ;│ █████ █ █ █ █ ███ █ █ █ │
- ;│ █ █ █ █ █ █ █ █ │
- ;│ █████ █ █ █████ █████ █████ V 1.0 │
- ;│ │
- ;│ │
- ;│ CODIGO PARA CREAR Y CONTROLAR DISQUETES │
- ;│ APROVECHANDO LA CAPACIDAD ANTES DE FORMATEAR │
- ;│ EN SISTEMAS PC, XT, AT - ISA/EISA/VLB/PCI (No MCA) │
- ;│ CON CONTROLADORAS Y UNIDADES DE ALTA DENSIDAD │
- ;│ │
- ;│ (C) 1994-1995 Ciriaco García de Celis. │
- ;│ Email: ciri@gui.uva.es │
- ;│ FidoNET 2:341/21.8 │
- ;│ Grupo Universitario de Informática │
- ;│ Facultad de Ciencias - Valladolid (España) │
- ;│ │
- ;│ Ensamblar con TASM 2mgui /m5 y enlazar con TLINK 2mgui │
- ;│ Se necesita el fichero 2MUTIL.INC incluído en 2M 3.0 │
- ;│ │
- ;└───────────────────────────────────────────────────────────────────┘
-
-
- ; ------------ Constantes fundamentales y valores por defecto.
-
- M_DMA EQU ON ; modo DMA por defecto
- FRONT EQU 28 ; pista de división del disco 360DH
- GAPDEF EQU 20 ; GAP anti-FIFO por defecto
- MODOWR EQU ON ; por defecto, caché de escritura
- W_CACHE_TM EQU 9 ; escritura retardada: 9/18 segundos
- PRE_GAP3 EQU 20 ; GAP3 para preformateo
- MPISTA EQU 30000 ; mayor pista absoluta posible
- PISTAS EQU 82 ; nº pistas por defecto
- SECTDEF EQU 128 ; tamaño de sector lógico por defecto
- CLUSDEF EQU 1024 ; tamaño de clúster por defecto
- MINROOT EQU 128 ; entradas raíz mínimo por defecto
- SLID_X EQU 55 ; sliding X por defecto (en grados)
- SLID_Y EQU 90 ; sliding Y por defecto (en grados)
-
- t_525_dd EQU 6098 ; tamaños recomendados (t_)
- m_525_dd EQU 6250 ; y límites teóricos por pista (m_)
- t_525_hd EQU 10239
- m_525_hd EQU 10416
- t_35_dd EQU 7343
- m_35_dd EQU 7500
- t_35_hd EQU 12313
- m_35_hd EQU 12500
- t_35_ed EQU 24626
- m_35_ed EQU 25000
-
- ; ------------ Macros de propósito general.
-
- XPUSH MACRO regmem ; apilar lista de registros
- IRP rm, <regmem>
- PUSH rm
- ENDM
- ENDM
-
- XPOP MACRO regmem ; desapilar lista de registros
- IRP rm, <regmem>
- POP rm
- ENDM
- ENDM
-
- XPUSHA MACRO
- XPUSH <AX, BX, CX, DX, SI, DI, BP>
- ENDM
-
- XPOPA MACRO
- XPOP <BP, DI, SI, DX, CX, BX, AX>
- ENDM
-
- DDS MACRO
- PUSH AX
- MOV AX,40h
- MOV DS,AX
- POP AX
- ENDM
-
- DELAY MACRO ; estados de espera
- JMP SHORT $+2 ; para AT obsoleto
- JMP SHORT $+2
- ENDM
-
- PMICRO MACRO ; retardo de aprox. 15,09 µs
- LOCAL pmicro_iter ; (exactamente 18/1193180 sg.)
- pmicro_iter: DELAY
- IN AL,61h ; Esta macro puede ejecutarse
- AND AL,10h ; repetitivamente (se apoya en
- CMP AL,AH ; AX) para hacer retardos a
- JE pmicro_iter ; través de la temporización
- MOV AH,AL ; del refresco de la memoria
- ENDM ; dinámica de los AT.
-
- ; ------------ Estructuras de datos.
-
- cab_PETICION STRUC ; parte inicial común a todos
- tamano DB ? ; los comandos de la cabecera
- unidad_disco DB ? ; de petición
- orden_dsp DB ?
- estado DW ?
- dos_info DB 8 DUP (?)
- cab_PETICION ENDS
-
- cab_INIT_BBPB STRUC ; para comandos INIT/BUILD_BPB
- DB (TYPE cab_PETICION) DUP (?)
- num_disc_init DB ? ; número de unidades definidas
- fin_resid_desp DW ? ; área que quedará residente
- fin_resid_segm DW ?
- bpb_cmd EQU THIS DWORD
- bpb_cmd_desp DW ? ; línea de órdenes del CONFIG
- bpb_cmd_segm DW ? ; y puntero al BPB
- nuevo_disco DB ? ; (DOS 3+) (0-A:, 1-B:,...)
- cab_INIT_BBPB ENDS
-
- cab_MEDIACHECK STRUC ; estructura para MEDIA CHECK
- DB (TYPE cab_PETICION) DUP (?)
- media_descrip DB ? ; descriptor de medio
- cambio DB ? ; 1: no cambiado, 0FFh:sí, 0:?
- cab_MEDIACHECK ENDS
-
- cab_READ_WRITE STRUC
- DB (TYPE cab_PETICION) DUP (?)
- DB ? ; descriptor de medio
- transfer_desp DW ? ; dirección de transferencia
- transfer_segm DW ?
- transfer_sect DW ? ; nº de sectores a transferir
- transfer_sini DW ? ; primer sector a transferir
- cab_READ_WRITE ENDS
-
- cab_GEN_IOCTL STRUC
- DB (TYPE cab_PETICION) DUP (?)
- categoria_cod DB ? ; código de categoría
- func_cod DB ? ; código de función
- copia_ds DW ?
- offset_cab DW ?
- ioctl_info DD ? ; puntero a información
- cab_GEN_IOCTL ENDS
-
- ; --- Estructura con información local a la unidad.
- ; Contiene información IOCTL, el BPB y otras.
-
- InfoBoot STRUC ; subestructura auxiliar
- vformat DW 0100h ; versión 1.0
- fformat DW 0 ; sin flags especiales en esta versión
- vunidad2 DB ? ; densidad segunda parte del disco
- mfrontera DB ? ; frontera divisora
- tpista1 DW ? ; tamaño físico pistas 0..FRONTERA-1
- tpista2 DW ? ; tamaño físico pistas FRONTERA..81
- idboot DW 0AA55h ; ID de sector válido
- InfoBoot ENDS
-
- info_unidad STRUC
- DB ? ; "sectores iguales" o no
- DB ? ; tipo (1-1.2, 7-1.44, 9-2.88)
- DW ? ; detección de cambio
- ioctl_pistas DW ? ; nº pistas
- ioctl_id DB '2'+'M' ; tipo de soporte
- bytes_sector DW ? ; BPB: bytes por sector
- sect_cluster DB ? ; BPB: sectores por cluster
- sect_reserv DW ? ; BPB: sectores reservados
- num_fats DB ? ; BPB: número de FATs
- entradas_raiz DW ? ; BPB: entradas en el raíz
- num_sect DW ? ; BPB: nº total de sectores
- media_byte DB ? ; BPB: descriptor de medio
- sectores_fat DW ? ; BPB: sectores por FAT
- sectores_pista DW ? ; BPB: sectores por pista
- num_cabezas DW ? ; BPB: cabezas
- sects_ocultos DD ? ; BPB: sectores ocultos
- DD 0 ; BPB: sectores (32bit)
- DB 11 DUP (0) ; BPB: restantes campos
- unidad DB ? ; unidad física
- tipo_drv DB 0 ; tipo de la disquetera (0 = no hay)
- modobios DB ON ; a ON si el disquete no es 2MGUI
- controldrv DB OFF ; a ON si el disco lo controla 2MGUI
- cambiodisco DB ON ; a ON por defecto para simular cambio
- cilindro DB ? ; cilindro del disco a acceder
- cabezal DB ? ; cabezal a emplear
- vunidad1 DB ? ; # velocidad primer medio disco
- infb InfoBoot <> ; información del BOOT
- tsector DB ? ; # LOG2 (tamaño buffer) redondeado
- prot_esc DB ? ; ON = disco protegido contra escritura
- numserie DD 12345678h ; número de serie del disco
- evol DB "NO NAME " ; etiqueta de volúmen (BOOT)
- fsystem DB "FAT12 " ; sistema de ficheros
- info_unidad ENDS
-
- ; ------------ Códigos de modos y órdenes del DMA, FDC,...
-
- BIOS_READ EQU 2
- BIOS_WRITE EQU 3
- F_READ EQU 46h ; modo DMA para lectura
- F_WRITE EQU 4Ah ; modo DMA para escritura
- F_VERIFY EQU 42h ; modo DMA para verificación
- F_FORMAT EQU 01001101b ; orden de formateo del FDC
- TICSTIMEOUT EQU 9322 ; constante para 2 segundos
- FD_STATUS EQU 3F4h ; registro de estado
- FD_DOR EQU 3F2h ; registro de salida digital
- FD_DIR EQU 3F7h ; registro de entrada digital
- FD_DCR EQU 3F7h ; registro de control disco
-
-
- ; ************ Inicio del área residente.
-
- _PRINCIPAL SEGMENT
- ASSUME CS:_PRINCIPAL, DS:_PRINCIPAL
-
- ORG 0
-
- ini_residente EQU $
-
- DD -1 ; encadenamiento con otros drivers
- tipo_drive DW 2840h ; palabra de atributo:
- ; bit 15 a 0: dispositivo de bloques
- ; bit 14 a 0: sin control IOCTL
- ; bit 13 a 1: SIN formato IBM
- ; bit 11 a 1: Open/Close/Remove
- ; bit 6 a 1: Generic Ioctl
- DW estrategia ; rutina de estrategia
- DW interrupcion ; rutina de interrupción
- num_discos DB 255 ; número de unidades (255 antes
- ; de que INIT lo inicialice)
-
- ; ***************************************************
- ; * *
- ; * D A T O S D E L C O N T R O L A D O R *
- ; * *
- ; ***************************************************
-
- ; ------------ Identificación estandarizada del programa.
-
- program_id LABEL BYTE
- segmento_real DW 0 ; segmento real donde será cargado
- offset_real DW 0 ; offset real " " "
- longitud_total DW 0 ; zona de memoria ocupada (párrafos)
- info_extra DB 03h ; bits 0, 1 y 2-> 000: normal, con PSP
- ; 001: bloque UMB XMS
- ; 010: *.SYS
- ; 011: *.SYS formato EXE
- ; bit 7 a 1: «extension_id» definida
- multiplex_id DB 0 ; número Multiplex de este TSR
- vectores_id DW tabla_vectores
- extension_id DW 0
- DB "*##*"
- autor_nom_ver DB "CiriSOFT:2MGUI:1.0",0
-
- DB 3 ; número de vectores de interrupción usados
- tabla_vectores EQU $
- DB 8h ; INT 8h
- ant_int08 LABEL DWORD ; dirección original
- ant_int08_off DW 0
- ant_int08_seg DW 0
- DB 13h ; INT 13h
- ant_int13 LABEL DWORD ; dirección original
- ant_int13_off DW 0
- ant_int13_seg DW 0
- DB 2Fh ; INT 2Fh
- ant_int2F LABEL DWORD ; dirección original
- ant_int2F_off DW 0
- ant_int2F_seg DW 0
-
- ; ------------ Datos de trabajo.
-
- pcab_peticion LABEL DWORD ; puntero a la cabecera de petición
- pcab_pet_desp DW 0
- pcab_pet_segm DW 0
-
- p_rutinas LABEL WORD ; tabla de rutinas del controlador
- DW init
- DW media_check
- DW build_bpb
- DW nofunc
- DW read
- DW read_nowait
- DW input_status
- DW input_flush
- DW write
- DW write_verify
- DW output_status
- DW output_flush
- DW ioctl_output
- DW open ; DOS 3.0+
- DW close ; DOS 3.0+
- DW remove ; DOS 3.0+
- DW nofunc
- DW nofunc
- DW nofunc
- DW generic_ioctl ; DOS 3.2+
-
- drv_pvars LABEL WORD ; punteros a variables y BPB
- DW info_E
- DW info_F
-
- bpb_ptrs LABEL WORD ; tabla de punteros BPB
- DW info_E.bytes_sector
- DW info_F.bytes_sector
-
- info_E info_unidad <> ; 2 BPB's para las 2 unidades
- info_F info_unidad <> ; posibles ya inicializados y
- ; sus variables particulares.
-
- info_BUF info_unidad <> ; para la pista en el buffer
-
- pet_fantasma cab_READ_WRITE <> ; cabecera de petición de
- ; solicitud fantasma
-
- ; ----- Variables de control globales.
-
- unidad_base DB ? ; primera letra de unidad definida
- tbase DW ? ; constante para retardos (XT)
- pcxt DB OFF ; a ON si no es AT
- drdos6 DB OFF ; a ON si es DR-DOS 6.0 ó Novell DOS 7.0
- tbuffer DW ? ; tamaño del buffer interno en bytes
- sbuffer DW ? ; puntero al segmento del buffer
- sbuf512 DW ? ; copia de seguridad del mismo
- ems_handle DW 0 ; handle EMS (si usado)
- marco_ems DW ? ; marco de página EMS (si usado)
- ems4 DB OFF ; a ON en EMS 4.0+
- SYSBYTES EQU 2 ; en cada pista, NOT(checksum) (2 bytes)
- gaprw DW GAPDEF ; GAP R/W simulado
- cachewr DB MODOWR ; modo para la caché de escritura
- modoDMA DB M_DMA ; modo DMA activo por defecto
- sentidoIO DB ? ; F_WRITE ó F_READ según operación NO-DMA
- bytesIO DW ? ; bytes para operación NO-DMA
- sector_ini DB ? ; número de sector inicial en los accesos
- sector_fin DB ? ; número de sector final en los accesos
- off_ini DW ? ; # offset inicial en la pista
- off_fin DW ? ; # offset final en la pista + 1
- bytes DW ? ; # bytes a transferir
- wrpend DB OFF ; a ON si pista en buffer aún no escrita
- expiraw DB ? ; contador de tics escritura retardada
- orden DB ? ; operación READ/WRITE
- verificar DB OFF ; a ON si WRITE VERIFY
- status DB ? ; resultado de los accesos a disco
- fdc_result DB 7 DUP (?) ; bytes de resultados del FDC
-
- ; --- Interpretación BIOS de los bits de ST1
-
- lista_errs DB 4 ; 'sector not found'
- DB 0
- DB 10h ; 'bad CRC'
- DB 8 ; 'DMA overrun'
- DB 0
- DB 4 ; 'sector not found'
- DB 3 ; 'write-protect error'
- DB 2 ; 'address mark not found'
- DB 20h ; en otro caso: 'bad NEC'
-
-
- ; *****************************************************
- ; * *
- ; * C O D I G O D E L C O N T R O L A D O R *
- ; * *
- ; *****************************************************
-
- ; ------------ Rutina de gestión de INT 2Fh.
- ; También se impide que SMARTDRIVE 4.0+ cachee por
- ; defecto las nuevas unidades (se cuelga al acceder si
- ; los sectores no son de 512 bytes).
-
- ges_int2F PROC FAR
- STI
- PUSH CX ; *
- CMP AX,4A10h
- JNE i2f_tsr ; no llama smartdrive
- CMP BX,6
- JNE i2f_tsr ; no llama smartdrive
- SUB CL,CS:unidad_base
- DEC CL
- JZ no_gracias ; llama smartdrive
- CMP CS:info_F.unidad,0
- JE i2f_tsr ; no llama para nuestra unidad
- DEC CL
- JNZ i2f_tsr ; no llama para nuestra unidad
- no_gracias: POP CX ; *1
- MOV AX,6 ; nos llama: "No, gracias"
- RETF 2
- i2f_tsr: POP CX ; *2
- CMP AH,CS:multiplex_id
- JE preguntan
- JMP CS:ant_int2F ; saltar al gestor de INT 2Fh
- preguntan: CMP DI,1992h
- JNE ret_no_info ; no llama alguien del convenio
- MOV AX,ES
- CMP AX,1492h
- JNE ret_no_info ; no llama alguien del convenio
- PUSH CS
- POP ES ; sí llama: darle información
- LEA DI,autor_nom_ver
- ret_no_info: MOV AX,0FFFFh ; "entrada multiplex en uso"
- IRET
- ges_int2F ENDP
-
- ; ------------ Rutina de gestión de INT 8. Se utiliza para grabar
- ; en disco el buffer con la pista pendiente de ser
- ; grabada (caché de escritura retardada) si pasa
- ; demasiado tiempo tras el último acceso.
-
- ges_int08 PROC FAR
- CLI ; por si llamada con CALL/JMP
- CMP CS:wrpend,OFF
- JE bye08
- DEC CS:expiraw
- JNZ bye08
- XPUSHA ; *
- XPUSH <DS, ES> ; **
- XPUSH <CS, CS>
- XPOP <DS, ES>
- MOV AL,20h
- OUT 20h,AL ; para que funcione IRQ6 ;-)
- CALL abs_flush
- XPOP <ES, DS> ; **
- XPOPA ; *
- bye08: JMP CS:ant_int08
- ges_int08 ENDP
-
- ; ------------ Rutina de gestión de INT 13h. Se utiliza para simular
- ; cambios de disco tanto en las nuevas unidades como en
- ; las normales, cuando el usuario conmuta entre ambas,
- ; ya que el primer acceso desde una de ellas baja la
- ; línea de cambio y ésta es la única manera de asegurar
- ; que la información del disco se corresponde con éste
- ; y no con otro antiguo ya sustituído.
-
- ges_int13 PROC FAR
- STI
- CMP DL,2
- JB ges_swp
- bios13: JMP CS:ant_int13
- ges_swp: CMP AH,2
- JB bios13
- CMP AH,16h
- JE simcamb?
- CMP AH,5
- JA bios13
- simcamb?: PUSH BX
- LEA BX,info_E ; apuntar datos unidad
- CMP CS:[BX].unidad,DL
- JE tab_dat_ok
- LEA BX,info_F
- CMP CS:[BX].unidad,DL
- JE tab_dat_ok
- POP BX
- JMP bios13
- tab_dat_ok: CMP CS:[BX].controldrv,ON
- MOV CS:[BX].controldrv,OFF ; simular cambio de disco
- MOV CS:[BX].cambiodisco,ON ; en nueva unidad
- POP BX
- JNE bios13
- STC
- MOV AH,6
- RET 2 ; y en la A: ó B:
- ges_int13 ENDP
-
- ; ------------ Rutina de estrategia.
-
- estrategia PROC FAR
- MOV CS:pcab_pet_desp,BX
- MOV CS:pcab_pet_segm,ES
- RET
- estrategia ENDP
-
- ; ------------ Rutina de interrupción.
-
- interrupcion PROC FAR
- STI
- XPUSHA
- XPUSH <DS, ES>
- LDS BX,CS:pcab_peticion
- MOV AL,[BX].orden_dsp ; AL = orden
- MOV AH,0 ; AX = orden
- CMP AL,13h
- JBE orden_ok ; orden soportada
- MOV AX,8103h ; orden desconocida
- JMP exit_interr
- orden_ok: SHL AX,1 ; orden = orden * 2
- MOV DI,AX
- ADD DI,OFFSET p_rutinas
- LEA SI,drv_pvars
- MOV AL,[BX].unidad_disco
- CMP AL,CS:num_discos
- JB disco_ok
- MOV AX,8101h ; unidad desconocida
- JMP exit_interr
- disco_ok: MOV AH,0
- SHL AX,1
- ADD SI,AX
- MOV SI,CS:[SI] ; SI -> BPB y juego variables
- XPUSH <BX,DS>
- CALL CS:[DI] ; ejecutar orden
- XPOP <DS,BX>
- exit_interr: MOV [BX].estado,AX
- XPOP <ES, DS>
- XPOPA
- RET
- interrupcion ENDP
-
- ; ------------ Las rutinas que controlan el dispositivo devuelven AX
- ; con la palabra de estado. Pueden cambiar todos los
- ; registros, incluídos los de segmento. A la entrada,
- ; DS:BX apunta a la cabecera de petición de solicitud y
- ; CS:SI al BPB y las variables de la unidad invocada.
-
- read_nowait: ; órdenes ignoradas...
- input_status:
- input_flush:
- output_status:
- output_flush:
- ioctl_output:
- open:
- close:
- remove: ; dispositivo removible
- retorno_ok: MOV AX,100h
- RET
-
- nofunc: MOV AX,8103h ; orden no soportada
- RET
-
- ; --- Soporte IOCTL.
- ; - Implementa las funciones:
- ; 60h - Obtener parámetros del dispositivo
- ; 66h - Devolver nº de serie (para el DIR)
- ; 41h - Escritura de pista (para DISKCOPY)
- ; 61h - Lectura de pista (para DISKCOPY)
- ; - Ignora las funciones:
- ; 40h - Establecer parámetros del dispositivo
- ; 46h - Establecer nº de serie
- ; - Indica siempre que no está permitido:
- ; 42h - Formatear y verificar pista
- ; 62h - Verificar pista
- ; - Retorna error de "no soportado" en las demás
-
- generic_ioctl: LDS BX,CS:pcab_peticion
- CMP [BX].categoria_cod,8
- JNE gen_ioctl_rtf
- MOV AL,[BX].func_cod
- CMP AL,60h ; soportado subcódigo 60h
- JE get_devp
- CMP AL,66h ; 66h
- JE get_serie
- CMP AL,46h ; 46h
- JE set_serie
- CMP AL,40h ; 40h
- JE set_devp
- CMP AL,41h ; 41h
- JE wr_ioctl
- CMP AL,61h ; y 61h
- JE rd_ioctl
- CMP AL,42h
- JE ioct_nosup
- CMP AL,62h
- JE ioct_nosup
- gen_ioctl_rtf: MOV AX,8103h ; orden no soportada
- RET
- get_devp: LES DI,[BX].ioctl_info ; orden 0860h invocada
- TEST BYTE PTR ES:[DI],1
- JZ devp ; no acceder a disco
- XPUSHA
- XPUSH <DS, ES>
- CALL build_bpb ; actualizar datos
- XPOP <ES, DS>
- XPOPA
- devp: INC SI
- INC DI
- MOV CX,38
- PUSH CS
- POP DS
- CLD
- REP MOVSB
- set_devp: JMP gen_ioctl_ret ; subcódigo 40h ignorado
- get_serie: LES DI,[BX].ioctl_info
- ADD DI,2
- PUSH CS
- POP DS
- LEA SI,[SI].numserie
- MOV CX,23
- CLD
- REP MOVSB ; devolver nº serie y demás
- set_serie: JMP gen_ioctl_ret ; no implementado cambiarlo
- ioct_nosup: LES DI,[BX].ioctl_info
- MOV BYTE PTR ES:[DI],2
- MOV AX,8107h ; no soportado format/verify
- RET
- gen_ioctl_ret: MOV AX,100h ; Ok
- RET
- wr_ioctl: CALL ioctl_io_info
- AND AX,AX
- JNZ noserie
- MOV AX,ES:[DI+39] ; actualizar número de
- MOV CX,ES:[DI+41] ; serie en memoria
- LEA DI,[SI].numserie
- MOV CS:[DI],AX
- MOV CS:[DI+2],CX
- noserie: CALL io_drdos
- CALL write
- RET
- rd_ioctl: CALL ioctl_io_info
- CALL io_drdos
- CALL read
- RET
-
- ioctl_io_info: LES DI,[BX].ioctl_info
- MOV AX,ES:[DI+3] ; cilindro
- MUL CS:[SI].num_cabezas
- ADD AX,ES:[DI+1] ; cabezal
- MUL CS:[SI].sectores_pista
- ADD AX,ES:[DI+5] ; AX = sector inicial
- MOV CX,ES:[DI+7] ; CX = número sectores
- LES DI,ES:[DI+9] ; ES:DI = dirección E/S
- PUSH CS
- POP DS
- LEA BX,pet_fantasma
- MOV [BX].transfer_desp,DI
- MOV [BX].transfer_segm,ES
- MOV [BX].transfer_sect,CX ; nº sectores
- MOV [BX].transfer_sini,AX ; primer sector
- RET
-
- ; --- El diskcopy de DR-DOS 6.0+ empieza a copiar
- ; por el final, descendentemente. Para evitar la
- ; inevitable recalibración en cada pista al tener
- ; que ir una pista atrás, se copia al revés ;-)
-
- io_drdos PROC
- CMP drdos6,ON
- JNE io_dr_ok
- CMP [SI].sectores_pista,1
- JNE io_dr_ok ; no es un disco 2MGUI
- MOV AX,[SI].num_sect
- SUB AX,[BX].transfer_sini
- SUB AX,[BX].transfer_sect
- MOV [BX].transfer_sini,AX ; sector opuesto
- io_dr_ok: RET
- io_drdos ENDP
-
- ; ------------ Rutina de detección de cambio de disco.
-
- media_check: CMP CS:[SI].cambiodisco,ON
- MOV CS:[SI].cambiodisco,OFF
- MOV CS:[SI].controldrv,ON
- MOV AL,0FFh ; supuesto cambio de disco
- JE set_cambio ; disco recién formateado
- MOV DL,CS:[SI].unidad
- CALL leer_lin_camb ; en 1.2M/1.44M/2.88M...
- JNZ set_cambio
- MOV AL,1 ; sin cambio de disco
- set_cambio: MOV [BX].cambio,AL
- MOV AX,100h
- RET
-
- ; ------------ Devolver ZF=1 si la línea de cambio de disco está
- ; inactiva. A la entrada, DL contiene la unidad. El
- ; motor es puesto en marcha y, si no lo estaba ya, la
- ; variable que indica lo que resta para detenerlo
- ; es llevada a su valor normal, por lo que el disco no
- ; tardará mucho en detenerse (incluso sin quizá haber
- ; acelerado aún).
-
- leer_lin_camb PROC
- XPUSHA ; *
- PUSH DS
- DDS
- MOV AL,1
- MOV CL,DL
- SHL AL,CL ; bit de motor en 0..3
- TEST DS:[3Fh],AL
- JNZ rodando ; el motor ya está girando
- CLC
- CALL motor_off_cnt ; cuenta normal detención motor
- rodando: MOV AH,DL
- MOV CL,4
- SHL AH,CL
- OR AH,AL ; AH = byte BIOS
- SHL AL,CL
- OR AL,00001100b ; modo DMA, no hacer reset
- OR AL,DL ; AL para reg. salida digital
- MOV DX,FD_DOR
- CLI
- MOV DS:[3Fh],AH ; actualizar variable BIOS
- OUT DX,AL ; arrancado motor en la unidad
- ADD DX,5
- DELAY
- IN AL,DX ; leer línea de cambio de disco
- STI
- TEST AL,80h ; ZF=0 -> cambio de disco
- POP DS
- XPOPA ; *
- RET
- leer_lin_camb ENDP
-
- ; ------------ Como el disco no es de tipo IBM, el DOS no intentará
- ; leer el primer sector de la FAT después de invocar
- ; media_check y antes de invocar build_bpb.
-
- build_bpb: XPUSH <CS, CS>
- XPOP <DS, ES>
-
- CALL abs_flush ; liquidar escritura pendiente
-
- det_media: MOV [SI].cilindro,0
- MOV [SI].cabezal,0
- MOV [SI].vunidad1,0
- MOV [SI].infb.vunidad2,0
- STC
- CALL reset_drv
- CALL motor_ok
- CALL seek_drv
-
- MOV [SI].tsector,7 ; todo menos 2.88M
- MOV CX,2
- intenta_2mg: CLC
- CALL reset_drv
- XOR DX,DX ; empezar por alta densidad
- densidad_2mg?: MOV [SI].vunidad1,DL
- MOV [SI].infb.vunidad2,DH
-
- CALL detect_2mgui
- JE detectado_2mg
- TEST status,80h
- JNZ proc_bios ; ¿unidad no preparada?
- ADD DX,0101h
- CMP DL,3
- JBE densidad_2mg? ; buscar densidad
- LOOP intenta_2mg
- JMP proc_bios
-
- detectado_2mg: XPUSH <AX, BX, DI> ; *
-
- MOV [SI].prot_esc,OFF ; supuesto no protegida...
- CALL test_st3
- JNC baja_lc
- MOV [SI].prot_esc,ON ; protegida contra escritura
-
- baja_lc: MOV [SI].cilindro,1
- CALL seek_drv
- MOV [SI].cilindro,0
- CALL seek_drv ; bajar línea cambio de disco
- MOV DX,FD_DIR
- IN AL,DX ; leer línea de cambio de disco
- MOV AH,80h
- TEST AL,AH ; ZF=0 -> cambio de disco
- XPOP <DI, BX, AX> ; *
- JNZ no_listo
- JMP s0_2mg_ok
-
- proc_bios: MOV CX,3
- intenta_bios: CALL detect_bios ; intentar acceso BIOS
- JNC s0_bios_ok
- LOOP intenta_bios
- no_listo: CMP AH,80h
- JE proc_err ; unidad no preparada
-
- CLC
- CALL reset_drv
- CALL motor_ok
- CALL seek_drv
- MOV [SI].tsector,8 ; ¿será 2.88M?
- MOV CX,2
- intenta_2mg28: MOV DX,0303h ; sólo extraalta densidad
- MOV [SI].vunidad1,DL
- MOV [SI].infb.vunidad2,DH
- CALL detect_2mgui
- JE detectado_2mg
- LOOP intenta_2mg28
-
- MOV AL,20h ; indicar 'anomalía general'
- proc_err: CALL errbios2dos
- MOV [SI].modobios,ON ; disco no-2MGUI
- RET
- s0_2mg_ok: MOV [SI].modobios,OFF ; disco 2MGUI
- MOV AL,7 ; log2 (16384) - 7 = 7
- CMP [SI].infb.tpista1,16384
- JBE tsec_ok
- INC AL ; log2 (32768) - 7 = 8
- tsec_ok: MOV [SI].tsector,AL
- MOV DS,sbuffer
- MOV BX,11
- JMP s0_dos
- s0_bios_ok: MOV [SI].modobios,ON ; disco no-2MGUI
- MOV DS,sbuffer
- MOV BX,11 ; offset en BOOT para el BPB
- CMP WORD PTR [BX],512 ; ¿sectores de 512?
- JE s0_dos
- MOV AX,8107h ; 'medio físico desconocido'
- RET
- s0_dos: PUSH SI ; *
- LEA DI,[SI].bytes_sector
- LEA SI,[SI].numserie
- XCHG SI,BX ; SI -> BPB del sector
- MOV CX,17
- XPUSH <SI, DI>
- CLD
- REP MOVSB ; construir BPB...
- XPOP <DI, SI>
- PUSH DI
- MOV DI,BX
- ADD SI,28 ; apuntar al nº serie y demás
- MOV CX,23
- REP MOVSB ; anotarlo
- POP DI
- POP SI ; *
- MOV AX,ES:[SI].sectores_pista
- MUL ES:[SI].num_cabezas
- MOV CX,AX
- MOV AX,ES:[SI].num_sect
- XOR DX,DX
- DIV CX
- MOV ES:[SI].ioctl_pistas,AX
- LDS BX,CS:pcab_peticion
- MOV [BX].bpb_cmd_desp,DI ; nuevo BPB obtenido
- MOV [BX].bpb_cmd_segm,CS
- MOV AX,100h ; Ok.
- RET
-
- ; --- Detectar un disco 2MGUI y devolver AX=tpista1
- ; y BX=tpista2
-
- detect_2mgui: XPUSH <CX, DX>
- MOV info_BUF.unidad,-1
- MOV [SI].cilindro,0
- MOV [SI].cabezal,0
- MOV AX,sbuf512
- MOV sbuffer,AX ; no usar EMS para esto
- MOV [SI].infb.tpista1,512 ; con 512 bytes basta
- MOV [SI].infb.mfrontera,86
- PUSH ES ; *
- MOV ES,sbuffer
- MOV ES:[PINFOBOOT].idboot,0
- POP ES ; *
- CLC
- CALL reset_drv
- CALL motor_ok
- CALL seek_drv
- CALL lee_pista
- CALL anotar_acceso
- XPUSH <DS, ES, SI> ; **
- PUSH DS
- POP ES
- MOV DS,sbuffer
- LEA DI,[SI].infb
- MOV SI,PINFOBOOT
- MOV CX,(TYPE InfoBoot) - 2 ; respetar marca 0xAA55
- CLD
- REP MOVSB ; anotar información física BOOT
- CMP WORD PTR DS:[PINFOBOOT].idboot,0AA55h ; ¿2MGUI?
- XPOP <SI, ES, DS> ; **
- XPOP <DX, CX> ; *
- RET
-
- ; --- Detectar un disco estándar.
-
- detect_bios: PUSH CX ; *
- MOV AH,0
- MOV DL,[SI].unidad
- PUSHF
- CALL CS:ant_int13 ; reset de disco
- media_detect: MOV info_BUF.unidad,-1 ; invalidar buffer
- PUSH ES ; **
- MOV ES,sbuffer
- XOR BX,BX
- MOV DL,[SI].unidad
- MOV DH,0
- MOV CX,1
- MOV AX,201h
- PUSHF
- CALL CS:ant_int13 ; leer sector de arranque
- POP ES ; **
- POP CX ; *
- RET
-
- ; --- Comprobar ST3 para saber si el disco está
- ; protegido contra escritura.
-
- test_st3 PROC
- PUSH AX
- MOV AL,4 ; comando para leer ST3
- CALL fdc_write
- JC st3_ok
- MOV AL,[SI].cabezal
- SHL AL,1
- SHL AL,1
- OR AL,[SI].unidad
- CALL fdc_write ; enviar HD, US1, US0
- JC st3_ok
- CALL fdc_read
- JC st3_ok
- TEST AL,64 ; ¿protegido contra escritura?
- JZ st3_ok
- POP AX
- STC
- RET
- st3_ok: POP AX
- CLC
- RET
- test_st3 ENDP
-
- ; ------------ Realizar lecturas y escrituras.
-
- read: MOV CS:verificar,OFF
- MOV CS:orden,BIOS_READ
- JMP prepara_io
-
- write_verify: MOV CS:verificar,ON
- MOV CS:orden,BIOS_WRITE
- JMP prepara_io
-
- write: MOV CS:verificar,OFF
- MOV CS:orden,BIOS_WRITE
-
- prepara_io PROC
- LES DI,DWORD PTR [BX].transfer_desp ; dirección
- MOV CX,[BX].transfer_sect ; nº sectores
- MOV BX,[BX].transfer_sini ; primer sector
- PUSH CS
- POP DS
- ADD BX,CX
- JNC io_ok? ; último sector < 65536
- io_no_ok: MOV AX,8108h ; error 'sector no encontrado'
- RET
- io_ok?: CMP BX,[SI].num_sect
- JA io_no_ok ; sector final ¡fuera!
- SUB BX,CX ; BX = primer sector
- prepara_io ENDP
- CMP [SI].modobios,ON
- JE calcula_dir ; disco soportado por la BIOS
- CMP ems_handle,0 ; disco soportado por 2MGUI
- JNE acc_ems
- JMP rwv2mgui ; no usada memoria EMS
- acc_ems: MOV DX,ems_handle ; usada memoria EMS
- MOV AH,47h
- XPUSH <BX, CX, SI, DI>
- INT 67h ; preservar el contexto
- XPOP <DI, SI, CX, BX>
- CMP AH,82h
- JE acc_ems ; reintentar
- AND AH,AH
- MOV AX,810Ch ; fallo: anomalía general
- JNZ rt_acc
- CALL rwv2mgui
- PUSH AX
- rrst: MOV DX,CS:ems_handle ; ¡DS corrompido si error!
- MOV AH,48h
- INT 67h ; restaurar el contexto
- CMP AH,82h
- JE rrst ; reintentar; si falla, pasar
- POP AX
- rt_acc: RET
-
- calcula_dir PROC
- MOV AX,[SI].sectores_pista
- MUL [SI].num_cabezas
- XCHG AX,BX
- XOR DX,DX
- DIV BX ; AX = cilindro, DX = resto
- MOV [SI].cilindro,AL
- MOV AX,DX
- XOR DX,DX
- DIV [SI].sectores_pista ; AX = cabezal, DX = sector
- MOV [SI].cabezal,AL
- INC DL
- MOV sector_ini,DL
- calcula_dir ENDP
-
- procesa_io PROC
- MOV AX,[SI].sectores_pista
- SUB AL,sector_ini
- INC AL ; AX sectores hasta fin pista
- final: CMP AL,CL
- JBE nsect_fp
- MOV AL,CL ; ¡no hay que acceder a tantos!
- nsect_fp: MOV AH,sector_ini
- ADD AH,AL
- DEC AH
- MOV sector_fin,AH ; sector ini/fin inicializados
- PUSH DS ; *
- XOR BX,BX
- MOV DS,BX
- LDS BX,DS:[1Eh*4] ; DS:BX -> tabla base disco
- CMP [BX+4],AH
- JAE ultsec_ok
- MOV [BX+4],AH ; sectores/pista necesarios
- ultsec_ok: MOV BYTE PTR DS:[BX+5],1 ; GAP R/W mínimo
- POP DS ; *
- XOR AH,AH
- SUB CX,AX ; restar los que se accederán
- PUSH CX
- MOV CX,3 ; 3 intentos como máximo
- reintentar_io: PUSH CX
- MOV AH,orden
- MOV CL,sector_ini
- MOV AL,sector_fin
- SUB AL,CL
- INC AL
- MOV CH,[SI].cilindro
- MOV DH,[SI].cabezal
- MOV DL,[SI].unidad
- MOV BX,DI
- PUSH AX
- PUSHF
- CALL ant_int13
- POP BX
- JC fallo_io ; ha habido fallo
- CMP verificar,ON
- CLC
- JNE io_ok
- MOV AH,4 ; verificar en write verify
- MOV CL,sector_ini
- MOV AL,sector_fin
- SUB AL,CL
- INC AL
- MOV CH,[SI].cilindro
- MOV DH,[SI].cabezal
- MOV DL,[SI].unidad
- MOV BX,DI
- PUSH AX
- PUSHF
- CALL ant_int13
- POP BX
- JC fallo_io
- JMP io_ok
- fallo_io: POP CX
- CMP AH,3
- JE proc_io_nok ; protegido contra escritura
- TEST AH,80h
- JNZ proc_io_nok ; unidad no preparada
- MOV AH,0
- PUSH CX
- PUSHF
- CALL ant_int13 ; reset de disco
- POP CX
- LOOP reintentar_io
- JMP proc_io_nok ; agotadas las oportunidades
- io_ok: MOV AH,BL
- SHL AH,1
- MOV AL,0
- ADD DI,AX ; ES:BX++
- POP CX ; contador de intentos
- POP CX ; sectores que restan
- JCXZ fin_io ; ¿más sectores a transferir?
- MOV sector_ini,1 ; ahora desde el primer sector
- INC [SI].cabezal ; de la siguiente cara
- MOV AX,[SI].num_cabezas
- CMP [SI].cabezal,AL
- JAE pr_step
- JMP procesa_io
- pr_step: MOV [SI].cabezal,0 ; o desde la primera cara
- INC [SI].cilindro ; del siguiente cilindro
- JMP procesa_io
- fin_io: MOV AX,100h ; Ok.
- RET
- proc_io_nok: POP CX
- LDS BX,pcab_peticion
- MOV [BX].transfer_sect,0 ; movidos 0 sectores
- MOV AH,1
- MOV DL,CS:[SI].unidad
- PUSHF
- CALL CS:ant_int13 ; obtener código de error BIOS
- CALL errbios2dos
- RET ; retornar con código error DOS
- procesa_io ENDP
-
- ; ------------ Traducir el error BIOS a código de error DOS.
-
- errbios2dos PROC
- MOV AL,0
- CMP AH,3 ; ¿protegido contra escritura?
- JE err_dos_ok
- MOV AL,8
- CMP AH,4 ; ¿sector no encontrado?
- JE err_dos_ok
- MOV AL,0Fh
- CMP AH,6 ; ¿cambio de disco no permitido?
- JE err_dos_ok
- MOV AL,4
- TEST AL,10h ; ¿error de CRC?
- JNZ err_dos_ok
- MOV AL,6
- TEST AH,40h ; ¿fallo posicionando cabezal?
- JNZ err_dos_ok
- MOV AL,2
- TEST AH,80h ; ¿unidad no preparada?
- JNZ err_dos_ok
- MOV AL,0Ch ; otro fallo: anomalía general
- err_dos_ok: MOV AH,81h
- RET
- errbios2dos ENDP
-
- ; ------------ Lectura, escritura y verificación en disco 2MGUI.
- ; A la entrada, ES:DI=dirección, BX=sectini, CX=nsects.
-
- rwv2mgui PROC
- MOV AX,[SI].bytes_sector
- MUL BX ; DX:AX = sector * tamaño
- XPUSH <CX, AX, DX> ; *
- MOV AX,[SI].infb.tpista1
- MOV BL,[SI].infb.mfrontera
- MOV BH,0
- SHL BX,1
- MUL BX ; DX:AX = tpista1 * frontera * 2
- XPOP <CX, BX> ; * CX:BX = offset en disco
- SUB BX,AX
- SBB CX,DX
- MOV [SI].cilindro,0 ; primera parte del disco
- JC rwv_cil_ok
- MOV AL,[SI].infb.mfrontera
- MOV [SI].cilindro,AL ; segunda parte del disco
- JMP rwv_off_ok
- rwv_cil_ok: ADD BX,AX
- ADC CX,DX ; restaurar offset
- rwv_off_ok: MOV DX,CX
- CALL tpistaAX
- XCHG AX,BX ; offset en DX:AX, BX = tpista
- POP CX ; *
- SHL BX,1 ; BX = tpista * 2
- DIV BX
- ADD [SI].cilindro,AL ; cilindro inicial
- MOV AX,DX
- XOR DX,DX ; DX:AX = resto división
- SHR BX,1
- DIV BX
- MOV [SI].cabezal,AL ; cabezal inicial
- MOV off_ini,DX ; offset inicial
- MOV AX,[SI].bytes_sector
- MUL CX
- MOV bytes,AX ; bytes a transferir
- MOV CX,3 ; reintentos en caso de error
- trans_mas: CMP bytes,0
- JE fin_trans
- PUSH CX
- CALL tpistaAX
- SUB AX,off_ini ; AX = bytes hasta final pista
- CMP AX,bytes
- JB ttrans_prep ; ocupa la pista hasta el final
- MOV AX,bytes
- ttrans_prep: ADD AX,off_ini
- MOV off_fin,AX
- CALL haz_io
- POP CX
- JNC ttrans_ok
- CMP status,3 ; error grave (prot. escrit.)
- JE err_trans
- TEST status,80h
- JNZ err_trans ; error grave (no preparada)
- CALL reset_drv
- LOOP trans_mas
- JMP err_trans ; fin de reintentos
- ttrans_ok: INC [SI].cabezal
- CMP [SI].cabezal,2
- JB incs_ok
- MOV [SI].cabezal,0
- INC [SI].cilindro
- incs_ok: MOV AX,off_fin
- SUB AX,off_ini
- MOV off_ini,0
- SUB bytes,AX
- JMP trans_mas
- err_trans: CLC
- CALL motor_off_cnt ; cuenta detención motor
- LDS BX,pcab_peticion
- MOV [BX].transfer_sect,0 ; movidos 0 sectores
- MOV AH,CS:status
- CALL errbios2dos
- RET
- fin_trans: CLC
- CALL motor_off_cnt ; cuenta detención motor
- MOV AX,100h
- RET
- rwv2mgui ENDP
-
- ; --- Transferir desde off_ini a off_fin
-
- haz_io PROC
- CALL direcc_ems ; direccionar memoria EMS
- JNC dirb_ok
- JMP ret_io ; fallo
- dirb_ok: CMP orden,BIOS_READ
- JNE escribir
- CALL leida?
- JNC upd_ok
- RET ; fallo en el flush
- upd_ok: JZ ahorra_lect ; pista ya leída
- CALL motor_ok
- CALL seek_drv
- CALL lee_pista
- CALL anotar_acceso
- JNC ahorra_lect
- RET ; fallo al leer
- ahorra_lect: MOV CX,off_fin
- SUB CX,off_ini
- XPUSH <DS, SI>
- MOV SI,off_ini
- MOV DS,sbuffer
- CLD
- REP MOVSB
- XPOP <SI, DS>
- CLC
- JMP ret_io
- escribir: CALL leida?
- JC ret_io ; fallo en el flush
- MOV CX,off_fin
- SUB CX,off_ini
- CALL tpistaAX
- CMP CX,AX
- JE escr_fast ; escribir pista completa
- CALL leida?
- JZ escr_fast ; pista ya en el buffer
- CALL motor_ok
- CALL seek_drv
- CALL lee_pista ; parcial: prelectura
- CALL anotar_acceso
- JC ret_io
- escr_fast: XPUSH <ES, DI> ; *
- XPUSH <DS, SI> ; **
- XPUSH <ES, DI>
- XPOP <SI, DS>
- MOV DI,CS:off_ini
- MOV ES,CS:sbuffer
- PUSH CX
- CLD
- REP MOVSB
- POP CX
- XPOP <SI, DS> ; **
- PUSH AX ; **
- MOV AL,[SI].cilindro
- OR AL,[SI].cabezal
- JNZ escr
- XPUSH <SI, CX> ; ***
- LEA SI,[SI].infb
- MOV DI,PINFOBOOT
- MOV CX,TYPE InfoBoot
- CLD
- REP MOVSB ; palabras de sólo lectura :-)
- XPOP <CX, SI> ; ***
- escr: POP AX ; **
- XPOP <DI, ES> ; *
- CALL escribir_pista ; "escribir" pista en disco
- CALL anotar_acceso
- JC ret_io
- ADD DI,CX ; actualizar offset
- CLC
- ret_io: RET
- haz_io ENDP
-
- ; --- Mapear memoria EMS si es utilizada.
-
- direcc_ems PROC
- PUSH SI
- CMP ems_handle,0
- JE seg_io_ok ; no usada EMS
- MOV AX,DI
- MOV CL,4
- SHR AX,CL
- MOV CX,ES
- ADD AX,CX ; AX = dirección lineal ES:DI
- MOV CX,marco_ems
- ADD CX,1024 ; CX = base página 1
- MOV BL,2 ; intentar usar página 2
- MOV DX,2048 ; offset de la página física 2
- CMP AX,CX
- JB map_pag
- XOR BL,BL ; usar la 0 para no colisionar
- MOV DX,0 ; offset de la página física 0
- map_pag: ADD DX,marco_ems
- MOV sbuffer,DX
- rmap_pag: MOV DX,ems_handle
- MOV AL,BL ; página física
- MOV AH,44h
- MOV BX,0 ; primera página lógica
- PUSH AX
- INT 67h ; mapear página
- POP BX
- CMP AH,82h
- JE rmap_pag ; reintentar
- AND AH,AH
- JNZ seg_io_ko
- CMP tbuffer,16384
- JBE seg_io_ok ; buffer de hasta 16K
- INC BL ; siguiente página física
- rmap2: MOV AL,BL
- MOV AH,44h
- MOV BX,1 ; segunda página lógica
- MOV DX,ems_handle
- PUSH AX
- INT 67h ; mapear página
- POP BX
- CMP AH,82h
- JE rmap2 ; reintentar
- AND AH,AH
- JNZ seg_io_ko
- seg_io_ok: CLC ; Ok
- POP SI
- RET
- seg_io_ko: MOV status,20h
- STC ; fallo
- POP SI
- RET
- direcc_ems ENDP
-
- ; --- Vaciar buffer a disco. Si se trabaja con EMS,
- ; previamente se mapea la memoria.
-
- abs_flush PROC
- CLI
- CMP wrpend,ON
- JE _abs_flush
- STI
- CLC
- RET
- _abs_flush: MOV wrpend,OFF
- STI
- CMP ems_handle,0
- JNE flush_ems
- JMP _flush_cache ; no usada memoria EMS
- flush_ems: MOV DX,ems_handle ; usada memoria EMS
- MOV AH,47h
- INT 67h ; preservar el contexto
- CMP AH,82h
- JE flush_ems ; reintentar
- AND AH,AH
- JNZ absf_ret
- CALL direcc_ems
- CALL _flush_cache
- PUSH AX
- rrst2: MOV DX,ems_handle
- MOV AH,48h
- INT 67h ; restaurar el contexto
- CMP AH,82h
- JE rrst2 ; reintentar
- POP AX
- absf_ret: RET
- abs_flush ENDP
-
- ; --- Vaciar buffer a disco. La escritura efectiva se
- ; retarda para reducir accesos redundantes.
-
- flush_cache PROC
- CLI
- CMP wrpend,ON
- JE _flush_cache
- STI
- CLC
- RET
- _flush_cache: MOV wrpend,OFF
- STI
- PUSH SI
- LEA SI,info_BUF
- CMP [SI].unidad,-1
- JE fc_ret
- CALL motor_ok
- CALL seek_drv
- CALL escribe_pista
- CALL anotar_acceso
- fc_ret: POP SI
- RET
- flush_cache ENDP
-
- ; --- Simular escritura en disco, aunque realmente se
- ; hará normalmente más tarde ("delayed write") a
- ; menos que esté activa la verificación.
-
- escribir_pista PROC
- CMP [SI].prot_esc,ON
- JNE wr_posible
- MOV status,3 ; protegida de escritura
- STC
- RET
- wr_posible: CMP verificar,ON
- JE wr_fisico ; verificación activa...
- CMP cachewr,ON
- JE delayed_wr
- wr_fisico: CALL motor_ok ; caché desactivada
- CALL seek_drv
- CALL escribe_pista
- JC wr_fs_ret
- CMP verificar,OFF
- JE wr_fs_ret ; CF=0
- CALL lee_pista ; detectar posible fallo
- wr_fs_ret: RET
- delayed_wr: MOV expiraw,W_CACHE_TM ; recargar contador de
- MOV wrpend,ON ; tiempo para escritura
- CLC ; retardada
- RET
- escribir_pista ENDP
-
- ; ------------ Comprobar si la pista está en el buffer. En caso de
- ; estarlo se retorna con ZF=1. Si no estaba aún, se
- ; vacía el contenido del buffer (si aún no estaba
- ; escrito en disco) en previsión de una futura
- ; lectura, retornando con ZF=0 (ó CF=1 si hay error
- ; al escribir).
-
- leida? PROC
- PUSH AX
- MOV AL,info_BUF.unidad
- CMP AL,[SI].unidad
- JNE no_leida ; es en otra unidad
- MOV AL,[SI].cilindro
- CMP AL,info_BUF.cilindro
- JNE no_leida
- MOV AH,[SI].cabezal
- CMP AH,info_BUF.cabezal
- JNE no_leida ; es en otro cilindro/cabezal
- POP AX
- RET ; está en el buffer CF=0, ZF=1
- no_leida: CALL flush_cache
- JC ret_leida? ; CF = 1 si error en el flush
- CMP SP,0
- CLC ; CF = ZF = 0
- ret_leida?: POP AX
- RET ; pista no leída
- leida? ENDP
-
- ; --- Tomar nota de la pista que ocupa el buffer para
- ; evitar accesos a disco redundantes. A la entrada,
- ; CF=1 señala error e invalida el buffer. Se anotan
- ; también los demás parámetros, necesarios para una
- ; posible escritura desde la interrupción periódica.
-
- anotar_acceso PROC
- MOV info_BUF.unidad,-1 ; invalidar buffer si error
- JC anotado
- XPUSH <CX, SI, DI, ES>
- PUSH DS
- POP ES
- LEA DI,info_BUF
- MOV CX,TYPE info_unidad
- CLD
- REP MOVSB
- XPOP <ES, DI, SI, CX>
- CLC
- anotado: RET
- anotar_acceso ENDP
-
- ; ------------ Devolver el tamaño de la pista según la posición
- ; del cabezal (necesario en discos /DH).
-
- tpistaAX PROC
- MOV AL,CS:[SI].infb.mfrontera
- CMP CS:[SI].cilindro,AL
- MOV AX,CS:[SI].infb.tpista1
- JB tpis_ax
- MOV AX,CS:[SI].infb.tpista2
- tpis_ax: RET
- tpistaAX ENDP
-
- ; ------------ Asegurar que el motor está en marcha.
-
- motor_ok PROC
- XPUSHA ; *
- PUSH DS ; **
- MOV BX,40h
- PUSH BX
- POP DS
- MOV CH,255-18 ; CH = 255 - 1 segundo
- CLI
- MOV CL,CS:[SI].unidad
- MOV AL,1
- SHL AL,CL
- TEST [BX-1],AL ; ¿motor en marcha?
- JZ arrancarlo ; arrancarlo
- CMP [BX],CH ; Si encendido y acelerado...
- JBE ok_motor ; ...seguir
- arrancarlo: MOV AH,CL
- MOV CL,4
- SHL AH,CL ; unidad << 4
- OR AL,AH
- MOV [BX-1],AL ; nuevo estado motores
- MOV BYTE PTR [BX],255 ; asegurar que no se pare
- MOV DX,FD_DOR ; registro de salida digital
- ADD CL,CS:[SI].unidad
- MOV AL,1
- SHL AL,CL ; colocar bit del motor
- OR AL,CS:[SI].unidad ; seleccionar unidad
- OR AL,00001100b ; modo DMA, no hacer reset
- OUT DX,AL ; poner en marcha el motor
- STI
- MOV AX,90FDh
- CLC
- INT 15h ; permitir multitarea
- JC ok_motor ; timeout
- MOV AX,1000 ; 1 segundo aceleración
- CALL retardo ; esperar aceleración disco
- ok_motor: MOV [BX],CH ; cuenta máxima detención motor
- STI ; sin forzar futura aceleración
- POP DS ; **
- XPOPA ; *
- RET
- motor_ok ENDP
-
- ; ------------ Establecer modalidad de operación del controlador
- ; y poner el motor en marcha. Si CF=1 se le da tiempo
- ; además a la unidad para que acelere.
-
- reset_drv PROC
- XPUSHA
- CALL motor_off_cnt ; cuenta detención motor
- STC
- CALL set_rate ; velocidad correcta
- MOV CL,[SI].unidad
- MOV AL,CL ; unidad seleccionada
- SHL AL,1
- SHL AL,1
- SHL AL,1
- SHL AL,1
- MOV AH,1 ; bit de motor
- SHL AH,CL ; colocar dicho bit
- OR AL,AH
- PUSH DS ; *
- DDS
- CLI
- MOV DS:[3Fh],AL
- AND BYTE PTR DS:[3Eh],70h ; bit IRQ=0 y recalibrar
- POP DS ; *
- SHL AL,1
- SHL AL,1
- SHL AL,1
- SHL AL,1 ; bits motor en nibble alto
- OR AL,CL ; seleccionar unidad
- OR AL,00001000b ; interrupciones+DMA y reset
- MOV DX,FD_DOR ; registro de salida digital
- OUT DX,AL ; señal de reset
- CALL fdc_respiro ; tiempo reconocer reset en 486
- OR AL,00000100b
- OUT DX,AL ; fin de señal de reset
- CALL reset_DMA
- CALL reset_irq
- CALL espera_int ; rehabilitará interrupciones
- AND status,7Fh ; perdonar controladora rara
- MOV AL,8
- CALL fdc_write ; comando 'leer estado int...'
- CALL fdc_read
- CALL fdc_read
- STC
- CALL envia_specify ; comando 'specify' adecuado
- XPOPA
- RET
- reset_drv ENDP
-
- ; ------------ Reset "blando" para que el FDC deje de enviar/recibir.
-
- reset_fast PROC
- XPUSHA
- MOV CL,[SI].unidad
- ADD CL,4
- MOV AL,1
- SHL AL,CL ; bits motor en nibble alto
- OR AL,[SI].unidad ; seleccionar unidad
- OR AL,00001000b ; interrupciones+DMA y reset
- MOV DX,FD_DOR ; registro de salida digital
- CLI
- OUT DX,AL ; señal de reset
- CALL fdc_respiro ; tiempo reconocer reset en 486
- OR AL,00000100b
- OUT DX,AL ; fin de señal de reset
- CALL reset_DMA
- CALL reset_irq
- CALL espera_int ; rehabilitará interrupciones
- AND status,7Fh ; perdonar controladora rara
- MOV AL,8
- CALL fdc_write ; comando 'leer estado int...'
- CALL fdc_read
- CALL fdc_read
- STC
- CALL envia_specify ; comando 'specify' con DMA
- XPOPA
- RET
- reset_fast ENDP
-
- ; ------------ Desactivar el modo DMA si procede (antes de leer o
- ; escribir). Además de enviar al FDC el comando specify
- ; adecuado, se selecciona el modo no-DMA (si fuera
- ; preciso) en el registro de salida digital (necesario en
- ; algunas controladoras).
-
- dma_si_o_no PROC
- CMP modoDMA,ON
- JE dmsnret
- XPUSHA
- MOV CL,[SI].unidad
- ADD CL,4
- MOV AL,1
- SHL AL,CL ; bits motor en nibble alto
- OR AL,[SI].unidad ; seleccionar unidad
- OR AL,00000100b ; modo no-DMA, sin reset
- MOV DX,FD_DOR
- OUT DX,AL
- CLC
- CALL envia_specify ; comando 'specify' adecuado
- XPOPA
- dmsnret: RET
- dma_si_o_no ENDP
-
- ; ------------ Inhibir y borrar petición en el canal 2 de DMA. No es
- ; realmente necesario, porque la controladora ya no
- ; transmite más después del reset, es sólo por seguridad.
-
- reset_DMA PROC
- PUSH AX
- MOV AL,2
- DELAY
- OUT 09h,AL ; borrar petición por software
- MOV AL,6
- DELAY
- OUT 0Ah,AL ; inhibir canal 2
- POP AX
- RET
- reset_DMA ENDP
-
- ; ------------ Borrar bit de interrupción pendiente para asegurar
- ; su correcta detección si llegó antes alguna inesperada,
- ; aunque realmente no tiene por qué suceder.
-
- reset_irq PROC
- PUSHF
- PUSH DS
- DDS
- AND BYTE PTR DS:[3Eh],7Fh ; asegurar detección int.
- POP DS
- POPF
- RET
- reset_irq ENDP
-
- ; ------------ Enviar comando specify a la controladora. El step-rate
- ; se selecciona según la densidad, para evitar un sonido
- ; extraño al posicionar o recalibrar el cabezal. A la
- ; entrada, CF=1 selecciona modo DMA y 0 no-DMA
-
- envia_specify PROC
- PUSH AX ; *
- PUSHF ; **
- PUSH DS
- DDS
- MOV AH,DS:[8Bh]
- POP DS
- MOV AL,3 ; comando 'specify'
- CALL fdc_write
- MOV AL,0BFh ; step rate para 500 kbps
- AND AH,11000000b
- JZ spec1_ok
- MOV AL,0AFh ; step rate para 1 Mbps
- CMP AH,11000000b
- JE spec1_ok
- MOV AL,0DFh ; step rate para 250/300 Kbps
- spec1_ok: CALL fdc_write
- MOV AL,2 ; modo DMA
- POPF ; **
- JC spec2_ok
- MOV AL,3 ; modo no DMA
- spec2_ok: CALL fdc_write
- POP AX ; *
- RET
- envia_specify ENDP
-
- ; ------------ Recargar cuenta para la detención del motor. Si CF=1 al
- ; entrar, se establece la mayor cuenta posible; en caso
- ; contrario, se pone el valor normal de la tabla base.
-
- motor_off_cnt PROC
- XPUSHA
- PUSH DS
- MOV AL,0FFh ; valor máximo
- JC motor_off_ok
- XOR BX,BX
- MOV DS,BX
- LDS BX,DWORD PTR DS:[1Eh*4] ; DS:BX -> INT 1Eh
- MOV AL,[BX+2] ; byte 2 tabla base disco
- motor_off_ok: DDS
- MOV BYTE PTR DS:[40h],AL ; cuenta parada motor
- POP DS
- XPOPA
- RET
- motor_off_cnt ENDP
-
- ; ------------ Llevar el cabezal a la pista indicada, recalibrando si
- ; hubo un reset (se invocó la función 0 de la INT 13h o
- ; se ejecutó reset_drv) antes de esta operación. Primero
- ; se selecciona la velocidad de transferencia y se borra
- ; el resultado de cualquier operación anterior, para que
- ; todo quede listo para el próximo acceso a disco.
-
- seek_drv PROC
- XPUSHA
- CLC
- CALL set_rate ; velocidad / borrar resultados
- STC
- CALL envia_specify ; comando 'specify' adecuado
- MOV AH,1
- MOV CL,[SI].unidad
- SHL AH,CL ; AH = 1 (A:) ó 2 (B:)
- PUSH DS
- DDS
- TEST AH,DS:[3Eh]
- POP DS
- JNZ do_seek ; la unidad ya fue recalibrada
- CALL recalibrar
- JC fallo_seek ; fallo al recalibrar
- do_seek: CMP [SI].cilindro,0
- JNE seek_deveras
- CALL recalibrar ; ir a la pista 0
- JMP seek_ok
- seek_deveras: MOV BX,94h
- ADD BL,[SI].unidad
- MOV AL,[SI].cilindro
- PUSH DS ; *
- DDS
- MOV CH,[BX] ; cilindro previo
- MOV [BX],AL ; nuevo cilindro
- POP DS ; *
- CMP AL,CH
- JE seek_ret ; seek innecesario
- hacer_seek: SUB AL,CH
- JC seek_neg ; seek hacia atrás
- seek_pos: CALL seek_fisico ; seek hacia delante
- JC fallo_seek
- JMP seek_ok
- seek_neg: ADD AL,CH
- CALL recalibrar ; ir a la pista 0
- MOV [SI].cilindro,AL
- JC fallo_seek
- JMP seek_deveras ; y luego a donde sea
- seek_ok: MOV AX,15 ; 15 milisegundos
- CALL retardo ; esperar asentamiento cabezal
- seek_ret: CLC ; retornar con éxito
- ret_seek: XPOPA
- RET
- fallo_seek: XPOPA
- STC ; retornar indicando fallo
- RET
-
- ; --- Como el registro interno de la controladora se
- ; pone a 0 tras el reset, el seek es por importe
- ; de la diferencia entre el cilindro origen y el
- ; destino (para retroceder se recalibra antes).
-
- seek_fisico: MOV CH,AL ; magnitud del "salto"
- MOV AL,0Fh
- CALL fdc_write ; comando 'seek'
- JC sk_fs_nok
- MOV AL,[SI].cabezal
- SHL AL,1
- SHL AL,1
- OR AL,[SI].unidad
- CALL fdc_write ; enviar HD, US1, US0
- MOV AL,CH ; cilindro aparente
- CALL reset_irq
- CALL fdc_write ; enviar cilindro
- CALL espera_int ; esperar interrupción
- JC sk_fs_nok
- MOV AL,8
- CALL fdc_write ; comando 'leer estado int...'
- JC sk_fs_nok
- CALL fdc_read ; leer registro de estado 0
- JC sk_fs_nok
- MOV AH,AL
- CALL fdc_read ; leer cilindro actual
- TEST AH,11000000b ; comprobar ST0
- JNZ sk_fs_nok
- sk_fs_ok: CLC
- RET
- sk_fs_nok: STC
- RET
- seek_drv ENDP
-
- ; ------------ Establecer velocidad de transferencia correcta si aún
- ; no ha sido seleccionada y borrar el resultado de otra
- ; operación previa. Si CF=1 al entrar, la velocidad se
- ; establece incondicionalmente (por si la variable de
- ; la BIOS no está correctamente asignada).
-
- set_rate PROC
- XPUSHA
- PUSHF
- MOV AL,[SI].infb.mfrontera
- CMP [SI].cilindro,AL
- MOV AL,[SI].vunidad1 ; velocidad primera parte
- MOV AH,[SI].infb.vunidad2 ; velocidad segunda parte
- JB vel_ok
- MOV AL,AH
- vel_ok: POPF
- PUSH DS ; *
- DDS
- JC abs_rate
- MOV AH,DS:[8Bh]
- MOV CL,6
- SHR AH,CL ; aislar bits de velocidad
- CMP AL,AH
- JE vel_set ; velocidad ya seleccionada
- abs_rate: MOV DX,FD_DCR
- OUT DX,AL ; seleccionarla
- MOV CL,6
- SHL AL,CL
- AND BYTE PTR DS:[8Bh],00111111b
- OR DS:[8Bh],AL
- vel_set: POP DS ; *
- LEA DI,status
- MOV CX,8
- borra_status: MOV [DI],CH ; borrar información de estado
- INC DI
- LOOP borra_status
- XPOPA
- RET
- set_rate ENDP
-
- ; ------------ Recalibrar la unidad (si hay error se intenta otra vez
- ; para el caso de que deba moverse más de 77 pistas).
-
- recalibrar PROC
- XPUSHA
- MOV BX,94h
- ADD BL,[SI].unidad
- PUSH DS ; *
- DDS
- MOV [BX],BH ; pista actual = 0
- POP DS ; *
- MOV CX,2 ; dos veces como mucho
- recalibra: MOV AL,7
- CALL fdc_write ; comando de 'recalibrado'
- JC fallo_recal
- MOV AL,[SI].cabezal
- SHL AL,1
- SHL AL,1
- OR AL,[SI].unidad
- CALL reset_irq
- CALL fdc_write ; enviar HD, US1, US0
- JC fallo_recal
- CALL espera_int ; esperar interrupción
- JC fallo_recal
- MOV AL,8
- CALL fdc_write ; comando 'leer estado int...'
- JC fallo_recal
- CALL fdc_read ; leer registro de estado 0
- JC fallo_recal
- MOV AH,AL
- CALL fdc_read ; leer cilindro actual
- XOR AH,00100000b ; bajar bit de 'seek end'
- TEST AH,11110000b ; comprobar resultado y ST0
- JNZ fallo_recal ; sin 'seek end' o TRK0
- MOV AX,1 ; pausa de 1 ms
- CALL retardo
- JMP recal_ret
- fallo_recal: CALL reset_fast
- LOOP recalibra ; reintentar comando
- STC ; condición de fallo
- XPOPA
- RET
- recal_ret: MOV AH,1
- MOV CL,[SI].unidad
- SHL AH,CL ; AH = 1 (A:) ó 2 (B:)
- MOV BX,94h
- ADD BL,CL
- PUSH DS
- DDS
- OR DS:[3Eh],AH ; unidad ya recalibrada
- POP DS
- CLC
- XPOPA
- RET
- recalibrar ENDP
-
- ; ------------ Escribir pista. En modo test (gaprw == -1) se escriben
- ; sólo los bytes de la pista (sin almacenar el checksum
- ; ni el GAP anti-FIFO).
-
- escribe_pista PROC
- XPUSHA
- CALL dma_si_o_no ; modo no-DMA si es preciso
- PUSH ES ; *
- MOV ES,sbuffer
- CALL tpistaAX
- MOV CX,AX
- XOR BX,BX
- XOR AX,AX
- MOV DX,2
- SHR CX,1
- PUSHF
- calc_chk: ADD AX,ES:[BX] ; calcular checksum en AX
- ADD BX,DX
- LOOP calc_chk
- POPF
- JNC fcalc_chk
- ADD AL,ES:[BX] ; nº de bytes impar
- ADC AH,0
- INC BX
- fcalc_chk: MOV CX,gaprw
- CMP CX,-1
- JE wfis1
- NOT AX
- MOV ES:[BX],AX ; NOT (checksum)
- JCXZ wfis1
- MOV AL,0
- gapw: MOV ES:[BX+2],AL ; "GAP"
- INC BX
- LOOP gapw
- wfis1: POP ES ; *
- CALL tpistaAX
- CMP gaprw,-1 ; ¿escritura de test?
- JE wfis2
- ADD AX,SYSBYTES
- ADD AX,gaprw ; bytes extra tras datos
- wfis2: MOV CX,AX
- DEC CX ; bytes totales - 1
- MOV AX,sbuffer
- XOR DI,DI
- CALL calc_dir_DMA ; AX:DI -> base BX y página AH
- MOV AL,F_WRITE ; modo DMA necesario
- CALL prepara_DMA
- MOV AL,11000101b ; comando de escritura del FDC
- CALL fdc_write
- JC escr_ko
- MOV AL,[SI].cabezal
- SHL AL,1
- SHL AL,1
- OR AL,[SI].unidad
- CALL fdc_write ; byte 1 de la orden
- MOV AL,[SI].cilindro
- CALL fdc_write ; enviar cilindro
- MOV AL,[SI].cabezal
- CALL fdc_write ; enviar cabezal
- MOV AL,0
- CALL fdc_write ; enviar nº sector
- MOV AL,[SI].tsector
- CALL fdc_write ; longitud sector
- MOV AL,0
- CALL fdc_write ; último sector
- MOV AL,8
- CALL fdc_write ; GAP no usado, pero...
- MOV AL,128
- CLI ; ir inhibiéndolas ya
- CALL fdc_write ; tamaño sector si longitud=0
- CALL espia_dma
- JMP escr_ret
- escr_ko: STC ; indicar fallo
- escr_ret: XPOPA
- RET
- escribe_pista ENDP
-
- ; ------------ Leer pista. En modo test (gaprw == -1) no se leen los
- ; bytes finales con el checksum (aunque sí se comparan al
- ; final: el error se debe desechar y comprobar el éxito
- ; de otra manera).
-
- lee_pista PROC
- XPUSHA
- CALL dma_si_o_no ; modo no-DMA si es preciso
- CALL tpistaAX
- CMP gaprw,-1
- JE rfis ; lectura de test
- ADD AX,SYSBYTES
- ADD AX,gaprw ; bytes extra tras datos
- rfis: MOV CX,AX
- DEC CX ; bytes totales - 1
- MOV AX,sbuffer
- XOR DI,DI
- CALL calc_dir_DMA ; AX:DI -> base BX y página AH
- MOV AL,F_READ ; modo DMA necesario
- CALL prepara_DMA
- MOV AL,11100110b ; comando de lectura del FDC
- CALL fdc_write
- MOV DL,20h
- JC leer_err
- MOV AL,[SI].cabezal
- SHL AL,1
- SHL AL,1
- OR AL,[SI].unidad
- CALL fdc_write ; byte 1 de la orden
- MOV AL,[SI].cilindro
- CALL fdc_write ; enviar cilindro
- MOV AL,[SI].cabezal
- CALL fdc_write ; enviar cabezal
- MOV AL,0
- CALL fdc_write ; enviar nº sector
- MOV AL,[SI].tsector
- CALL fdc_write ; longitud sector
- MOV AL,0
- CALL fdc_write ; último sector
- MOV AL,8
- CALL fdc_write ; GAP no usado, pero...
- MOV AL,128
- CLI ; ir inhibiéndolas ya
- CALL fdc_write ; tamaño sector si longitud=0
- CALL espia_dma
- JC leer_ret ; hubo error
- PUSH ES ; *
- MOV ES,sbuffer
- CALL tpistaAX
- MOV CX,AX
- XOR BX,BX
- XOR AX,AX
- MOV DX,2
- SHR CX,1
- PUSHF
- test_chk: ADD AX,ES:[BX] ; calcular checksum en AX
- ADD BX,DX
- LOOP test_chk
- POPF
- JNC ftest_chk
- ADD AL,ES:[BX] ; nº de bytes impar
- ADC AH,0
- INC BX
- ftest_chk: NOT AX ; NOT (checksum)
- MOV CX,ES:[BX] ; checksum en disco en CX
- POP ES ; *
- MOV DL,10h ; 'error de CRC'
- CMP AX,CX
- JNE leer_err
- CLC ; Ok
- JMP leer_ret
- leer_err: OR status,DL
- STC ; indicar fallo
- leer_ret: XPOPA
- RET
- lee_pista ENDP
-
- ; ------------ Cuando el DMA acabe... resetear controladora. A la
- ; entrada, las interrupciones deben estar inhibidas.
- ; Si no se emplea el DMA ... se resetea cuando se han
- ; enviado/recibido directamente los bytes necesarios.
- ; Se reprograma el 8254 para asegurar a ultranza que
- ; produce las 18,2 irqs/seg habituales y para contar
- ; exactamente el tiempo que pasará en esta rutina: la
- ; pérdida de exactitud que supone recargar la cuenta
- ; no se puede comparar ni remotamente a la de tener
- ; las interrupciones inhibidas ;-)
-
- espia_dma PROC
- XPUSH <ES, DI> ; *
- MOV ES,sbuffer
- MOV AL,00010110b
- OUT 43h,AL ; 8254: cnt0 byte bajo
- MOV AL,0
- DELAY
- OUT 40h,AL ; asegurar recarga = 0000h
- MOV AL,00100110b
- DELAY
- OUT 43h,AL ; 8254: cnt0 byte alto
- MOV AL,0
- DELAY
- OUT 40h,AL ; asegurar recarga = 0000h
- DELAY
- IN AL,40h
- MOV BL,AL ; estado de la cuenta alta
- MOV DX,FD_STATUS
- MOV CX,TICSTIMEOUT ; constante de timeout
- CMP modoDMA,ON
- JE wait_dma
- XOR DI,DI ; ES:DI -> sbuffer
- MOV AH,BL
- MOV BX,bytesIO
- CMP sentidoIO,F_READ
- JE rd_nodma
-
- wr_nodma: IN AL,DX ; transferencia sin DMA
- TEST AL,10000000b
- JNZ wr_byte
- IN AL,40h
- CMP AL,AH
- JE wr_nodma ; no han pasado 256/1193180 seg
- MOV AH,AL
- LOOP wr_nodma
- JMP io_timeout
- wr_byte: TEST AL,01000000b ; ¿fdc->cpu en vez de cpu->fdc?
- JNZ io_result ; así es: fallo en escritura
- MOV AL,ES:[DI]
- INC DX ; apuntar al registro de datos
- OUT DX,AL ; escribir byte de la pista
- DEC DX
- INC DI
- DEC BX
- JNZ wr_nodma ; hasta acabar pista
- JMP io_fin
-
- rd_nodma: IN AL,DX ; transferencia sin DMA
- TEST AL,10000000b
- JNZ rd_byte
- IN AL,40h
- CMP AL,AH
- JE rd_nodma ; no han pasado 256/1193180 seg
- MOV AH,AL
- LOOP rd_nodma
- JMP io_timeout
- rd_byte: TEST AL,00100000b ; ¿fase de ejecución?
- JZ io_result ; no: fallo en lectura
- INC DX ; apuntar al registro de datos
- IN AL,DX ; leer byte de la pista
- DEC DX
- STOSB
- DEC BX
- JNZ rd_nodma ; hasta acabar pista
- JMP io_fin
-
- wait_dma: IN AL,DX ; transferencia con DMA
- XOR AL,11000000b
- TEST AL,11000000b
- JZ io_result ; hay resultados del FDC
- IN AL,5
- MOV AH,AL
- IN AL,5 ; contador del canal 2
- CMP AX,-1
- JE io_fin ; fin de la cuenta del DMA
- IN AL,40h
- CMP AL,BL
- JE wait_dma ; no han pasado 256/1193180 seg
- MOV BL,AL
- LOOP wait_dma
-
- io_timeout: CALL reset_fast ; habilita ints (quita timeout)
- MOV status,80h ; recuperar condición timeout
- JMP io_ret_nok
- io_fin: IN AL,DX
- XOR AL,11000000b
- TEST AL,11000000b
- JZ io_result ; hay resultados del FDC
- CALL reset_fast ; habilita ints
- JMP io_ret_ok ; siempre ok
- io_result: CALL reset_DMA ; por si acaso
- STI
- LEA BX,fdc_result
- PUSH CX ; ** no corromper CX
- MOV CX,7
- io_leeres: CALL fdc_read ; leyendo resultados
- MOV [BX],AL
- INC BX
- LOOP io_leeres
- POP CX ; **
- CMP modoDMA,ON
- JE io_ret_nok
- MOV AL,status ; preservar resultado
- CALL reset_fast ; volver al modo DMA+INT
- MOV status,AL ; restaurar resultado
- io_ret_nok: CALL ajustar_hora
- XPOP <DI, ES> ; *
- STC ; retorno con error
- CALL set_err
- RET
- io_ret_ok: XPOP <DI, ES> ; *
- CALL ajustar_hora
- CLC ; retorno Ok
- RET
- espia_dma ENDP
-
- ; ------------ Leer el reloj de tiempo real y actualizar la hora.
- ; El acceso a disco con las interrupciones inhibidas
- ; retrasa brutalmente la hora. Si es un PC/XT, a la
- ; entrada CX indica las veces que le quedaban por cambiar
- ; a la parte alta de la cuenta del contador 0 del 8253
- ; desde que se inhibieron las interrupciones para que
- ; se hubiera producido un timeout.
-
- ajustar_hora PROC
- XPUSHA
- CMP CS:pcxt,ON
- JE ajuste_burdo ; jeje, pobrecillo XT
- CALL leer_RTC
- JNC actualiza_tm ; no hay actualización en curso
- JMP fin_ajuste
- ajuste_burdo: SUB CX,TICSTIMEOUT
- NEG CX ; tiempo transcurrido apróx.
- ADD CX,48 ; redondeo
- MOV CL,CH
- MOV CH,0
- SHR CX,1 ; expresado en 1/18,2-avos seg.
- PUSH DS
- DDS
- ADD CX,DS:[6Ch]
- MOV BX,DS:[6Eh]
- ADC BX,0
- POP DS
- JMP ajusta_bios
- actualiza_tm: MOV AL,DH ; segundos en BCD
- CALL convdec ; BCD (AL) -> decimal (AX)
- PUSH AX ; almacenar segundos
- MOV AL,CL ; minuto en BCD
- CALL convdec ; BCD (AL) -> decimal (AX)
- PUSH AX ; almacenar minuto
- MOV AL,CH ; hora en BCD
- CALL convdec ; BCD (AL) -> decimal (AX)
- MOV BX,60
- MUL BL ; AX = hora*60
- POP DX
- ADD AX,DX ; AX = hora*60+minuto
- MUL BX ; DX:AX = (hora*60+minuto)*60
- POP CX
- ADD CX,AX ; añadir segundos
- ADC DX,0
- MOV BX,DX ; BX:CX segundos totales
- MOV SI,CX
- MOV DI,BX ; DI:SI segundos totales
- MOV AX,18 ; (1193180 DIV 65536)
- CALL mult32x16 ; DI:SI = seg * 18
- XCHG SI,CX
- XCHG DI,BX ; BX:CX:XX = seg * 18 * 65536
- MOV AX,13532 ; (1193180 MOD 65536)
- CALL mult32x16
- ADD CX,DI
- ADC BX,0 ; BX:CX:SI = seg * 1193180
- ajusta_bios: PUSH DS
- DDS
- CMP BX,24
- JNE medianoche_ok
- CMP CX,176
- JB medianoche_ok
- XOR BX,BX
- SUB CX,176
- INC BYTE PTR DS:[70h] ; paso 23:59:59 --> 00:00:00
- medianoche_ok: MOV DS:[6Ch],CX
- MOV DS:[6Eh],BX ; BX:CX = seg * 1193180 / 65536
- POP DS
- fin_ajuste: XPOPA
- RET
- convdec: MOV AH,AL ; BCD en AL --> decimal en AX
- SHR AH,1
- SHR AH,1
- SHR AH,1
- SHR AH,1
- AND AL,15
- AAD
- RET
- ajustar_hora ENDP
-
- ; --- Obtener la hora del reloj de tiempo real SIN BIOS.
-
- leer_RTC PROC
- MOV AL,0Ah ; registro de estado A
- OUT 70h,AL
- DELAY
- IN AL,71h
- TEST AL,128
- JNZ tm_nok ; en medio de actualización
- MOV AL,4
- DELAY
- OUT 70h,AL
- DELAY
- IN AL,71h
- MOV CH,AL ; hora
- MOV AL,2
- DELAY
- OUT 70h,AL
- DELAY
- IN AL,71h
- MOV CL,AL ; minuto
- MOV AL,0
- DELAY
- OUT 70h,AL
- DELAY
- IN AL,71h
- MOV DH,AL ; segundo
- CLC
- RET
- tm_nok: STC
- RET
- leer_RTC ENDP
-
- ; ------------ Rutina para multiplicar números de 32 por números de 16
- ; bits generando resultado de 48 bits: DXDISI = DISI * AX
-
- mult32x16 PROC
- PUSH AX
- XCHG SI,AX ; multiplicador en SI
- MUL SI ; AX (parte baja) * SI --> DXAX
- XPUSH <DX, AX> ; preservar resultado parcial
- MOV AX,DI
- MUL SI ; AX (parte alta) * SI --> DXAX
- XPOP <SI, DI> ; parte baja y media del resultado
- ADD DI,AX ; acumular resultado intermedio
- ADC DX,0 ; arrastrar posible acarreo
- POP AX
- RET
- mult32x16 ENDP
-
- ; ------------ Devolver en AH la página de DMA y en BX la base. A la
- ; entrada, AX:DI -> dirección de memoria.
-
- calc_dir_DMA PROC
- PUSH DX
- MOV BX,16
- MUL BX
- ADD AX,DI
- ADC DX,0 ; DX:AX = dirección 20 bits
- MOV BX,AX ; base en BX
- MOV AH,DL ; página
- dir_DMA_ok: POP DX
- RET
- calc_dir_DMA ENDP
-
- ; ------------ Determinar el tipo de error producido en el acceso.
-
- set_err PROC
- XPUSHA
- JNC err_ret ; no hay error
- CMP status,0 ; ¿'status' ya asignado?
- JNE err_retc ; no cambiarlo si es así
- MOV AL,BYTE PTR fdc_result+1
- AND AL,10110111b ; aislar condiciones de test
- LEA BX,lista_errs
- MOV CX,9
- busca_err: MOV AH,[BX] ; código de error BIOS
- SHL AL,1
- JC err_ok ; es ese error
- INC BX
- LOOP busca_err ; buscar otro error
- err_ok: OR status,AH
- err_retc: STC ; condición de error
- err_ret: XPOPA
- RET
- set_err ENDP
-
- ; ------------ Esperar interrupción de disquete durante casi 2
- ; segundos antes de considerar que ha sido un fracaso.
-
- espera_int PROC
- STI
- XPUSHA
- XPUSH <DS, 40h>
- POP DS
- MOV AX,9001h
- CLC
- INT 15h ; permitir multitarea
- JC timeout_int
- MOV AH,0FFh
- esperar_int: CMP AL,DS:[6Ch]
- JE mira_int
- MOV AL,DS:[6Ch]
- INC AH
- CMP AH,37 ; ¿más de 2 segundos?
- JB mira_int
- timeout_int: OR CS:status,80h ; timeout
- STC
- JMP fin_espera
- mira_int: TEST BYTE PTR DS:[3Eh],80h
- JZ esperar_int
- AND BYTE PTR DS:[3Eh],7Fh ; CF=0
- fin_espera: POP DS
- XPOPA
- RET
- espera_int ENDP
-
- ; ------------ Preparar DMA para E/S. A la entrada, BX = dirección de
- ; base, AH = registro de página y CX = nº bytes - 1.
-
- prepara_DMA PROC
- CMP modoDMA,ON
- JE _prepara_DMA
- MOV sentidoIO,AL
- MOV bytesIO,CX
- INC bytesIO
- RET ; modo NO-DMA
- _prepara_DMA: PUSH AX
- CLI
- OUT 0Bh,AL ; registro de modo del DMA
- MOV AL,0
- DELAY
- OUT 0Ch,AL ; clear first/last flip-flop
- MOV AL,BL
- DELAY
- OUT 4,AL
- MOV AL,BH
- DELAY
- OUT 4,AL ; enviada dirección base
- DELAY
- MOV AL,AH
- OUT 81h,AL ; registro de página del DMA
- MOV AL,CL
- DELAY
- OUT 5,AL
- MOV AL,CH
- DELAY
- OUT 5,AL ; enviada cuenta de bytes
- STI
- MOV AL,2
- DELAY
- OUT 0Ah,AL ; habilitar canal 2 de DMA
- POP AX
- RET
- prepara_DMA ENDP
-
- ; ------------ Recibir byte del FDC en AL. A la vuelta, CF=1 si
- ; la operación fracasó (el FDC no estaba listo) y
- ; se indica la condición de timeout en «status».
-
- fdc_read PROC
- CMP CS:pcxt,ON
- JE fdc_read_xt
- XPUSH <CX, DX, AX>
- CALL fdc_respiro ; no abrasar el FDC
- MOV DX,FD_STATUS ; registro de estado del FDC
- MOV CX,133 ; constante para 0,002 segundos
- espera_rd: DELAY
- IN AL,DX
- AND AL,11000000b
- CMP AL,11000000b ; ¿dato listo?
- JE fdc_rd_ok
- DELAY
- IN AL,61h
- AND AL,10h
- CMP AL,AH
- JE espera_rd ; reintentarlo durante 15,09 µs
- MOV AH,AL
- LOOP espera_rd
- XPOP <AX, DX, CX>
- OR status,80h ; timeout
- MOV AL,0
- STC ; fallo
- RET
- fdc_rd_ok: POP AX
- INC DX ; apuntar al registro de datos
- DELAY
- IN AL,DX ; leer byte del FDC
- XPOP <DX, CX>
- CLC ; Ok
- RET
- fdc_read ENDP
-
- fdc_read_xt PROC
- XPUSH <CX, DX>
- MOV DX,FD_STATUS ; registro de estado del FDC
- XOR CX,CX ; evitar cuelgue total si falla
- espera_rd_xt: IN AL,DX ; leer registro de estado
- TEST AL,80h ; ¿bit 7 inactivo?
- LOOPZ espera_rd_xt ; así es: el FDC está ocupado
- JCXZ fdc_rd_nok_xt
- INC DX ; apuntar al registro de datos
- IN AL,DX ; leer byte del FDC
- CLC
- XPOP <DX, CX>
- RET
- fdc_rd_nok_xt: OR status,80h ; timeout
- STC
- XPOP <DX, CX>
- RET
- fdc_read_xt ENDP
-
- ; ------------ Enviar byte AL al FDC. A la vuelta, CF=1 si
- ; la operación fracasó (el FDC no estaba listo) y
- ; se indica la condición de timeout en «status».
-
- fdc_write PROC
- CMP CS:pcxt,ON
- JE fdc_write_xt
- XPUSH <CX, DX, AX>
- CALL fdc_respiro ; no abrasar el FDC
- MOV DX,FD_STATUS ; registro de estado del FDC
- MOV CX,133 ; constante para 0,002 segundos
- espera_wr: DELAY
- IN AL,DX
- TEST AL,80h ; ¿listo para E/S?
- JNZ fdc_wr_ok
- DELAY
- IN AL,61h
- AND AL,10h
- CMP AL,AH
- JE espera_wr ; reintentarlo durante 15,09 µs
- MOV AH,AL
- LOOP espera_wr
- XPOP <AX, DX, CX>
- OR status,80h ; timeout
- STC ; fallo
- RET
- fdc_wr_ok: INC DX ; apuntar al registro de datos
- POP AX
- DELAY
- OUT DX,AL ; enviar byte al FDC
- XPOP <DX, CX>
- CLC ; Ok
- RET
- fdc_write ENDP
-
- fdc_write_xt PROC
- XPUSH <AX, CX, DX>
- MOV DX,FD_STATUS ; registro de estado del FDC
- XCHG AH,AL ; preservar AL en AH
- XOR CX,CX ; evitar cuelgue total si falla
- espera_wr_xt: IN AL,DX ; leer registro de estado
- TEST AL,80h ; ¿bit 7 inactivo?
- LOOPZ espera_wr_xt ; así es: el FDC está ocupado
- JCXZ fdc_wr_nok_xt
- XCHG AH,AL ; recuperar el dato de AL
- INC DX ; apuntar al registro de datos
- OUT DX,AL ; enviar byte al FDC
- XPOP <DX, CX, AX>
- CLC
- RET
- fdc_wr_nok_xt: OR status,80h ; timeout
- XPOP <DX, CX, AX>
- STC
- RET
- fdc_write_xt ENDP
-
- ; ------------ Retardo de 60 µs para dar tiempo al FDC en 486 rápidos.
-
- fdc_respiro PROC
- CMP CS:pcxt,ON
- JNE fdc_resp_at
- PUSH CX
- MOV CX,50
- respiro: LOOP respiro ; retardo en PC/XT
- POP CX
- RET
- fdc_resp_at: XPUSH <AX, CX>
- MOV CX,4
- fdc_ret: PMICRO
- LOOP fdc_ret
- XPOP <CX, AX>
- RET
- fdc_respiro ENDP
-
- ; ------------ Esperar exactamente AX milisegundos.
-
- retardo PROC
- PUSHF
- XPUSHA
- CMP CS:pcxt,ON
- JE retardo_xt
- MOV DX,16970 ; 16970 = 1193180/18*256/1000
- MUL DX
- MOV CL,AH ; dividir DX:AX entre 256 y
- MOV CH,DL ; dejar el resultado en DX:CX
- MOV DL,DH
- MOV DH,0 ; DX:CX 15,09 µs-avos
- retardando: PMICRO
- LOOP retardando
- AND DX,DX
- JZ retardado
- DEC DX
- JMP retardando
- retardado: XPOPA
- POPF
- RET
-
- retardo_xt: CMP AX,54 ; como máximo 54 ms cada vez
- JBE retarda_fin
- PUSH AX
- MOV AX,54
- CALL rt_ax
- POP AX
- SUB AX,54
- JMP retardo_xt
- retarda_fin: CALL rt_ax
- JMP retardado
-
- rt_ax: MOV DX,1000 ; retardo de hasta 54 ms
- MUL DX
- MUL CS:tbase
- MOV CX,54925
- DIV CX ; AX = contador iteraciones
- MOV CX,AX
- EVEN ; forzar alineamiento
- retarda: DEC CX
- JMP SHORT $+2
- JNZ retarda
- RET
- retardo ENDP
-
- EVEN
- ini_buffer EQU $ ; comienzo del buffer E/S
-
- fin_residente EQU $ ; fin del área residente sin contar el buffer
-
- bytes_resid EQU fin_residente-ini_residente
-
-
-
- ; ****************************************************************
- ; * *
- ; * I N S T A L A C I O N D E S D E E L C O N F I G *
- ; * *
- ; ****************************************************************
-
- init PROC
- LEA DX,retorno_ok
- MOV CS:p_rutinas,DX ; anular 'init'
-
- LES BP,[BX].bpb_cmd ; apuntar a los parámetros
- LEA AX,bpb_ptrs
- MOV [BX].bpb_cmd_desp,AX
- MOV [BX].bpb_cmd_segm,CS ; tabla punteros a BPB's
- XPUSH <DS, BX>
- PUSH CS
- POP DS ; DS: -> _PRINCIPAL
- MOV BX,BP
- CALL salta_nombre
- LEA BP,parametros
- CALL obtener_param
- CALL testAT
- JC init_m1 ; en PC/XT, siempre DMA
- CMP param_nodma,OFF
- JE init_m1
- MOV modoDMA,OFF ; en AT, permitir NO-DMA
-
- init_m1: CALL inic_general
- CMP param_b,ON
- JNE init_m2
- MOV AX,tpista ; /B permite modificar el
- MOV tbuffer,AX ; tamaño del buffer
- init_m2: CALL inic_ioctl
- MOV AL,num_discos
- XPOP <BX, DS>
- MOV [BX].num_disc_init,AL
- MOV AH,[BX].nuevo_disco ; unidad en DOS 3.0+
- XPUSH <CS, CS>
- XPOP <DS, ES> ; DS y ES: -> _PRINCIPAL
- TEST error,0FFFFh
- JZ cont_instala1
- JMP salida_error
- cont_instala1: MOV unidad_base,AH
- CALL genera_nombre ; de AL unidades desde AH
- CALL analiza_equipo ; ¿ordenador adecuado?
- TEST error,0FFFFh
- JZ cont_instala2
- JMP salida_error
- cont_instala2: CMP instalado,ON
- JNE cont_instala3
- OR error,YAINST
- JMP salida_error
- cont_instala3: CALL mx_get_handle ; obtener código Multiplex
- JNC handle_ok
- OR error,MX64FULL ; no quedan entradas
- JMP salida_error
- handle_ok: MOV multiplex_id,AH ; entrada multiplex
- CALL preservar_ints ; tomar nota de vectores
- LEA BX,ini_buffer+15
- MOV CL,4
- SHR BX,CL
- MOV AX,CS
- ADD AX,BX
- MOV sbuffer,AX
- MOV sbuf512,AX
- CMP param_nodma,ON
- JNE usar_dma ; DMA usado
- CMP param_ems,ON
- JNE init_tsr
- CALL alloc_EMS ; poner buffer en EMS
- JMP init_tsr
- usar_dma: MOV BX,tbuffer
- CALL getdmaok
- AND BX,BX
- JZ dmaguay ; no hay problemas de DMA
- MOV sbuffer,AX ; arreglar cruce frontera
- MOV sbuf512,AX
- ADD tbuffer,BX
- OR error,DMACRUCE ; ¡maldita frontera!
- dmaguay: CALL vds_dma_ok?
- MOV emmtipo,BX ; tipo de EMM
- JNC init_tsr
- OR error,DMAPOCO ; poco buffer DMA en EMM
- init_tsr: CALL inicializa_id
- MOV DI,100h ; ORG 0 (compensar COM)
- CALL activar_ints ; interceptar vectores
- LEA DX,programa_txt ; mensaje de instalación
- CALL print
- LEA DX,instalado_txt
- CALL print
- CMP pcxt,ON
- JNE ins_at
- CMP param_nodma,OFF
- JE ins_at
- LEA DX,errxtdma_txt ; PC/XT necesita DMA
- CALL print
- ins_at: TEST error,DMACRUCE
- JZ buffernormal
- LEA DX,dma_front_txt
- CALL print ; aviso de frontera DMA
- buffernormal: TEST error,DMAPOCO
- JZ bastantedma
- LEA DX,dma_poco_txt
- CALL print ; aviso de poco buffer DMA
- CMP emmtipo,"QE"
- LEA DX,crlf_txt
- JNE pr_emm
- LEA DX,emm_qemm_txt
- pr_emm: CALL print ; informar de QEMM
- bastantedma: CMP param_ems,ON
- JNE ems_ok
- CMP ems_handle,0
- JNE ems_ok
- LEA DX,erremsins_txt
- CMP param_nodma,ON
- JE err_ems_ok
- LEA DX,erremsdma_txt
- err_ems_ok: CALL print
- ems_ok: MOV AX,longitud_total
- MOV CL,4
- SHL AX,CL
- LDS BX,CS:pcab_peticion
- MOV [BX].fin_resid_desp,AX
- MOV [BX].fin_resid_segm,CS
- MOV AX,100h ; instalación Ok.
- RET
- salida_error: LEA DX,programa_txt
- CALL print
- LEA DX,mal_dos_txt ; errores posibles
- TEST error,MALDOS ; desde el CONFIG
- JNZ prn_error
- LEA DX,mal_bios_txt
- TEST error,MALBIOS
- JNZ prn_error
- LEA DX,mal_drv_txt
- TEST error,MALDRV
- JNZ prn_error
- LEA DX,err_sintax_txt
- TEST error,ERRSINTAX ; ¿error de sintaxis?
- JNZ prn_error
- LEA DX,nocabe_txt
- TEST error,MX64FULL
- JNZ prn_error
- LEA DX,ya_ins_txt
- prn_error: CALL print ; imprimir error
- LDS BX,CS:pcab_peticion
- MOV [BX].fin_resid_desp,0 ; OFFSET 0 indica que no
- MOV [BX].fin_resid_segm,CS ; quedará instalado
- MOV AX,100h ; indicar retorno correcto
- RET
- init ENDP
-
-
- ; ********************************************************************
- ; * *
- ; * C O D I G O E J E C U T A D O D E S D E E L D O S *
- ; * *
- ; ********************************************************************
-
- main PROC FAR
- MOV BX,_PILA
- SUB BX,_PRINCIPAL ; tamaño de este programa
- ADD BX,tampila/16+17 ; más pila y más PSP
- MOV AH,4Ah ; cambiar memoria asignada
- INT 21h
- MOV AX,_PRINCIPAL ; programa de un segmento
- MOV DS,AX ; DS: -> _PRINCIPAL
- LEA BP,parametros
- MOV BX,81h
- MOV psp,ES ; anotar PSP
- CALL obtener_param ; procesar parámetros
- PUSH DS
- POP ES ; ES: -> _PRINCIPAL
- JNC test_pmts
- JMP informar ; error/ayuda
- test_pmts: CMP param_nodma,ON
- JNE cont_ins
- CMP param_test,ON
- JE cont_ins
- pmt_config: OR error,PARAMCONFIG ; parámetro del CONFIG.SYS
- JMP informar
- cont_ins: CMP param_ems,ON
- JE pmt_config
- CALL null_param?
- JNE proceder
- CALL analiza_equipo
- CMP instalado,ON
- JNE ayudar ; no instalado y sin parámetros
- CALL adaptar_param ; parámetros en copia residente
- CALL informe ; informe de unidades/opciones
- JMP fin
- ayudar: MOV param_ayuda,ON
- JMP informar ; no indicados parámetros
- proceder: CALL inic_general
- CALL analiza_equipo
- TEST error,0FFFFh XOR MALDRV
- JNZ informar ; error != MALDRV
- CALL adaptar_param ; parámetros en copia residente
- CMP param_test,ON
- JE testear
- CMP instalado,ON
- JE ya_reside
- OR error,NOINST ; programa no instalado
- JMP informar ; (obligarlo para formatear)
- ya_reside: CALL setbuffer
- JC informar
- MOV AL,maxpistas
- CMP frontera,AL
- JBE fr_ok
- MOV frontera,AL ; limitar alcance frontera
- fr_ok: CALL format_disk
- JMP fin
- testear: CALL setbuffer
- JC informar
- CALL test_disk ; calcular mayor capacidad
- JMP fin
- informar: CALL info
- MOV AX,error
- fin: MOV AH,4Ch
- INT 21h ; final
- main ENDP
-
-
- ;*********************************************************
- ;* *
- ;* SUBRUTINAS DE PROPOSITO GENERAL PARA LA INSTALACION *
- ;* *
- ;*********************************************************
-
- INCLUDE 2MUTIL.INC
-
- ; ------------ Saltar nombre del driver en línea de órdenes del CONFIG
-
- salta_nombre PROC
- MOV AL,ES:[BX]
- INC BX
- CMP AL,' '
- JE fin_nombre
- CMP AL,9
- JE fin_nombre
- CMP AL,0Dh
- JE fin_nombre
- CMP AL,0Ah
- JE fin_nombre
- AND AL,AL
- JZ fin_nombre
- JMP salta_nombre
- fin_nombre: RET
- salta_nombre ENDP
-
- ; ------------ Nombrar las unidades (AL) a partir de la número AH.
-
- genera_nombre PROC
- MOV CL,AL
- MOV CH,0 ; CX = nº unidades
- MOV AL,AH
- ADD AL,'A'
- MOV AH,':'
- LEA SI,tabla_letras1
- LEA DI,tabla_letras2
- init_nombres: MOV [SI],AX
- MOV [DI],AX
- ADD SI,3
- ADD DI,3
- INC AL
- LOOP init_nombres
- RET
- genera_nombre ENDP
-
- ; ------------ Inicializar ciertas variables.
-
- inic_general PROC
- CALL testDRDOS
- CALL testAT
- JNC skip_tmtest ; en AT no calcularlo [*]
- CALL cte_tiempos
- MOV tbase,AX ; cte. retardo para 1/18,2 seg.
- skip_tmtest:
- MOV num_discos,0
- MOV DL,0
- CALL tipo_disco
- JNC hay_unidad
- MOV DL,1
- CALL tipo_disco
- JNC hay_unidad
- OR error,MALBIOS ; no hay disqueteras
- RET
- hay_unidad: MOV disco,0
- MOV DL,disco
- CALL tipo_disco
- CMP BL,2
- JE tipoE_HD
- CMP BL,4
- JAE tipoE_HD ; hallada A: de alta densidad
- INC disco
- MOV DL,disco
- CALL tipo_disco
- CMP BL,2
- JE tipoE_HD
- CMP BL,4
- JAE tipoE_HD ; hallada B: de alta densidad
- OR error,MALDRV
- RET
- tipoE_HD: MOV info_E.tipo_drv,BL ; guardar tipo unidad
- MOV AL,disco
- MOV info_E.unidad,AL ; y si es la A: ó B:
- ADD info_E.ioctl_id,AL
- INC num_discos ; de momento, 1 unidad
- CMP AL,1
- JE fin_inic ; procesadas A: y B:
- MOV DL,1
- CALL tipo_disco
- CMP BL,2
- JE tipoF_HD
- CMP BL,4
- JB fin_inic ; hallada B: de alta densidad
- tipoF_HD: MOV info_F.tipo_drv,BL ; guardar tipo unidad
- MOV info_F.unidad,1 ; y que es la B:
- ADD info_F.ioctl_id,1
- INC num_discos ; 2 unidades controladas
-
- fin_inic: MOV AX,m_35_ed ; buffer para 2.88M
- CMP info_E.tipo_drv,5
- JAE inic_buff
- CMP info_F.tipo_drv,5
- JAE inic_buff
- MOV AX,m_35_hd ; buffer para 1.44M
- CMP info_E.tipo_drv,4
- JE inic_buff
- CMP info_F.tipo_drv,4
- JE inic_buff
- MOV AX,m_525_hd ; buffer para 1.2M
- inic_buff: MOV tbuffer,AX
- RET
- inic_general ENDP
-
- ; --- Comprobar si es DR-DOS 6.0 ó Novell DOS 7.0
-
- testDRDOS PROC
- MOV AX,4452h
- INT 21h
- JC drdos_tst
- CMP AL,67h
- JB drdos_tst
- MOV drdos6,ON ; DR-DOS 6 / Novell DOS 7
- drdos_tst: RET
- testDRDOS ENDP
-
- ; ------------ Inicializar la información IOCTL de las unidades.
- ; Se asume que sólo DS apunta a los datos.
-
- inic_ioctl PROC
- PUSH ES ; *
- PUSH DS
- POP ES
- LEA DI,info_E
- CALL inic_ioct_DI
- LEA DI,info_F
- CALL inic_ioct_DI
- POP ES ; *
- RET
-
- inic_ioct_DI: MOV AL,[DI].tipo_drv
- LEA SI,info_drv288
- CMP AL,5
- JAE info_drv_ok
- LEA SI,info_drv120
- CMP AL,2
- JE info_drv_ok
- LEA SI,info_drv144
- info_drv_ok: MOV CX,6
- CLD
- REP MOVSB
- INC SI ; respetar byte tipo soporte
- INC DI
- MOV CX,31
- REP MOVSB
- RET
- inic_ioctl ENDP
-
- ; ------------ Comprobar que la configuración es la adecuada.
-
- analiza_equipo PROC
- CALL residente?
- MOV AL,OFF
- JC set_resid
- MOV AL,ON
- set_resid: MOV instalado,AL
- MOV AH,30h
- INT 21h
- XCHG AH,AL
- CMP AX,31Eh ; ¿DOS 3.30 o superior?
- MOV AX,MALDOS
- JB pc_nok
- CALL testAT
- MOV pcxt,OFF
- JNC pc_ok
- MOV pcxt,ON
- JMP pc_ok
- pc_nok: OR error,AX
- pc_ok: RET
- analiza_equipo ENDP
-
- ; ----- Detectar 286 ó superior.
-
- testAT PROC
- PUSHF
- POP AX
- OR AH,70h ; intentar activar bit 12, 13 ó 14
- PUSH AX ; del registro de estado
- POPF
- PUSHF
- POP AX
- AND AH,0F0h
- CMP AH,0F0h
- JE testedAT
- STC
- testedAT: CMC ; CF = 0 en AT y 1 en PC/XT
- RET
- testAT ENDP
-
- ; ------------ Comprobar si es un 386+
-
- es386? PROC
- PUSHF
- POP AX
- OR AH,70h ; intentar activar bit 12, 13 ó 14
- PUSH AX ; del registro de estado
- POPF
- PUSHF
- POP AX
- AND AH,0F0h
- CMP AH,0F0h
- MOV AL,0
- JE fin_test_CPU ; es 8086 o similar
- AND AH,70h ; 286 pone bits 12, 13 y 14 a cero
- JZ fin_test_CPU ; es 286
- MOV AL,1 ; 386 o superior
- fin_test_CPU: MOV AH,0
- CMP AX,1
- RET
- es386? ENDP
-
- ; ------------ Calcular la constante de retardo básica para perder
- ; exactamente 54,925 ms. Con una regla de 3 se podrá
- ; después aplicar para hacer retardos de milisegundos
- ; en los PC/XT.
-
- cte_tiempos PROC
- XPUSH <DS, ES, BX, CX, DX>
- MOV AX,3508h
- INT 21h
- XPUSH <ES, BX> ; preservar vector de INT 8
- PUSH DS
- MOV AX,40h
- MOV DS,AX
- MOV AL,DS:[6Ch]
- espera_i8: CMP AL,DS:[6Ch]
- JE espera_i8 ; esperar INT 8 ... para que no
- POP DS
- LEA DX,i8_crono ; venga otra en un buen rato...
- MOV AX,2508h
- INT 21h ; nueva rutina de INT 8
- IN AL,21h
- PUSH AX ; preservar estado de IRQ's
- MOV AL,11111110b
- OUT 21h,AL ; permitir sólo IRQ0
- MOV AH,0 ; fase
- MOV CX,0 ; contador
- MOV BX,CX ; seguiría a 0 si fallara
- EVEN ; forzar alineamiento
- cuenta_iter: DEC CX ; <─┐ bucle básico de retardo
- JMP SHORT $+2 ; │
- JNZ cuenta_iter ; <─┘ lo interrumpirá INT 8
- POP AX ; anterior estado de IRQ's
- OUT 21h,AL
- XPOP <DX, DS>
- PUSH BX ; valor real contado
- MOV AX,2508h ; restaurar vector de INT 8
- INT 21h
- POP AX ; (65536-AX) vueltas en 54,9 ms
- NEG AX ; constante de retardo básica
- XPOP <DX, CX, BX, ES, DS>
- RET
- i8_crono: INC AH ; nueva INT 8 que interrumpe
- CMP AH,1 ; el bucle de retardo
- JE fase1
- CMP AH,2
- JE fase2
- i8_exit: MOV AL,20h
- OUT 20h,AL
- IRET
- fase1: MOV CX,0 ; sincronizar con el reloj
- JMP i8_exit
- fase2: MOV BX,CX ; anotar constante de retardo
- MOV CX,1 ; forzar fin del bucle
- JMP i8_exit
- cte_tiempos ENDP
-
- ; ------------ Inicializar área «program_id» del programa residente.
-
- inicializa_id PROC
- MOV segmento_real,CS ; anotar segmento del bloque
- MOV offset_real,0 ; ídem con el offset
- MOV AX,bytes_resid ; tamaño área residente
- ADD AX,tbuffer ; tamaño buffer residente
- ADD AX,31 ; redondeo (programa+buffer)
- CMP ems_handle,0
- JE mem_AX
- MOV AX,bytes_resid ; tamaño área residente
- ADD AX,512+SYSBYTES+GAPDEF+31 ; minibuffer+redondeo
- mem_AX: MOV CL,4
- SHR AX,CL
- MOV longitud_total,AX
- OR info_extra,3 ; SYS en formato EXE
- RET
- inicializa_id ENDP
-
- ; ------------ Ubicar el buffer interno en EMS.
-
- alloc_EMS PROC
- PUSH ES
- MOV AX,3567h
- INT 21h ; vector de INT 67h en ES:BX
- MOV DI,10
- LEA SI,emm_id
- MOV CX,8
- CLD
- REP CMPSB ; ¿instalado controlador EMS?
- POP ES
- JE hay_emm
- JMP finprep_emm
- hay_emm: MOV CX,8000h ; nº de intentos prudente
- emm_llama: MOV AH,40h
- INT 67h
- AND AH,AH
- JZ emm_responde
- CMP AH,82h
- LOOPE emm_llama
- JMP finprep_emm ; no funciona ¿?
- emm_responde: MOV AH,41h
- INT 67h
- AND AH,AH
- JZ emm_pag_ok
- CMP AH,82h
- JE emm_responde ; reintentar (EMM ocupado)
- JMP finprep_emm
- emm_pag_ok: MOV marco_ems,BX ; inicializar marco EMS
- MOV AH,46h
- INT 67h ; obtener versión del EMM
- CMP AL,40h
- JB emm_obt_kb ; versión anterior a la 4.0
- MOV ems4,ON
- emm_obt_pag: XPUSH <ES,DS>
- POP ES
- MOV AX,5800h ; obtener dirección de páginas
- LEA DI,buffer_aux
- INT 67h
- POP ES
- AND AH,AH
- JZ emm_pags_ok
- CMP AH,82h
- JE emm_obt_pag
- JMP finprep_emm
- emm_pags_ok: LEA SI,buffer_aux
- CLD
- emm_otra_pag: LODSW
- MOV BX,AX ; BX = segmento de la página
- LODSW ; AX = nº de la página
- AND AX,AX
- JE hallada_pag0 ; encontrada página 0
- LOOP emm_otra_pag
- JMP finprep_emm
- hallada_pag0: LODSW ; segmento página 1
- SUB AX,BX
- CMP AX,1024 ; ¿(pag1 - pag0) != 1024?
- JNE finprep_emm ; páginas no contiguas
- LODSW
- LODSW ; segmento página 2
- SUB AX,BX
- CMP AX,2048 ; ¿(pag2 - pag0) != 2048?
- JNE finprep_emm ; páginas no contiguas
- LODSW
- LODSW ; segmento página 3
- SUB AX,BX
- CMP AX,3072 ; ¿(pag3 - pag0) != 3072?
- JNE finprep_emm ; páginas no contiguas
- emm_obt_kb: MOV BX,tbuffer
- ADD BX,16383 ; BXi = redondeo
- ROL BX,1
- ROL BX,1
- AND BX,3 ; BX = BXi / 16384
- MOV AH,43h
- INT 67h
- AND AH,AH
- JZ ems_alloc_ok
- CMP AH,82h
- JE emm_obt_kb ; reintentar (EMM ocupado)
- JMP finprep_emm
- ems_alloc_ok: MOV ems_handle,DX
- CMP ems4,ON
- JNE finprep_emm
- MOV AX,5301h
- LEA SI,emm_nombre
- INT 67h
- finprep_emm: RET
- alloc_ems ENDP
-
- ; ------------ Devolver ZF=1 si no se indica ningún parámetro.
-
- null_param? PROC
- MOV AH,param_ayuda
- OR AH,param_dd
- OR AH,param_dh
- OR AH,param_ed
- OR AH,param_k
- OR AH,param_n
- OR AH,param_test
- OR AH,param_t
- OR AH,param_r
- OR AH,param_s
- OR AH,param_f
- OR AH,param_b
- OR AH,param_x
- OR AH,param_y
- OR AH,param_m
- NOT AH
- MOV AL,disquetera
- XOR AX,ptr_label
- XOR AX,ptr_ilabel
- CMP AX,-1
- RET
- null_param? ENDP
-
- ; ------------ Informar al usuario.
-
- info PROC
- CMP param_ayuda,ON ; ¿solicitud de ayuda?
- JNE info_normal
- LEA DX,ayuda_txt
- CALL print
- JNC fin_info
- LEA DX,limpia_txt ; se pulsó ESC en la ayuda
- CALL print
- JMP fin_info
- info_normal: LEA DX,programa_txt
- CALL print
- LEA DX,mal_dos_txt
- TEST error,MALDOS ; ¿DOS incorrecto?
- JZ otroerr2
- CALL print
- otroerr2: LEA DX,mal_bios_txt
- TEST error,MALBIOS ; ¿BIOS obsoleta?
- JZ otroerr3
- CALL print
- otroerr3: LEA DX,err_sintax_txt
- TEST error,ERRSINTAX ; ¿error de sintaxis?
- JZ otroerr4
- CALL print
- LEA DX,pet_ayuda_txt
- CALL print
- otroerr4: LEA DX,no_ins_txt
- TEST error,NOINST ; ¿no instalado en CONFIG?
- JZ otroerr5
- CALL print
- otroerr5: LEA DX,err_mem_txt
- TEST error,POCAMEM ; ¿poca memoria?
- JZ otroerr6
- CALL print
- otroerr6: LEA DX,pconfig_txt
- TEST error,PARAMCONFIG ; ¿parámetro del CONFIG?
- JZ fin_info
- CALL print
- fin_info: RET
- info ENDP
-
- ; ------------ Establecer el buffer que no cruce con el DMA.
-
- setbuffer PROC
- MOV AH,48h
- MOV BX,MPISTA*2/16
- INT 21h
- JNC haymem
- OR error,POCAMEM
- STC
- RET
- haymem: MOV BX,MPISTA ; mayor buffer posible
- CALL getdmaok ; AX = segmento no conflictivo
- MOV sbuffer,AX
- MOV sbuf512,AX
- CLC
- RET
- setbuffer ENDP
-
- ; ------------ Obtener un segmento no conflictivo con el DMA. A la
- ; entrada, AX=segmento propuesto y BX=tamaño buffer en
- ; bytes. A la salida, AX podría haber sido incrementado
- ; y BX indicaría en cuántos bytes.
-
- getdmaok PROC
- XPUSH <CX, DX>
- SHR BX,1
- SHR BX,1
- SHR BX,1
- SHR BX,1 ; bytes tamaño -> párrafos
- MOV CX,AX
- MOV DX,BX
- ADD DX,AX ; DX = segmento final
- AND DH,0F0h ; página del segmento final
- AND CH,0F0h ; página del segmento inicial
- MOV BX,0 ; supuesto ajuste nulo
- CMP CH,DH
- JE buff_ok ; no hay problemas con DMA
- MOV DL,0 ; DX = nuevo segmento
- MOV BX,DX
- SUB BX,AX ; incremento relativo
- MOV AX,DX
- buff_ok: MOV CL,4
- SHL BX,CL ; incremento relativo en bytes
- XPOP <DX, CX>
- RET
- getdmaok ENDP
-
- ; ------------ Comprobar si el buffer para el DMA es suficiente, en
- ; caso de haber un controlador de memoria. Se devuelve
- ; el código de identificación del controlador en BX, o
- ; un valor 1234h si no hay controlador; DI indica el
- ; tamaño de buffer soportado y CF=1 si no basta.
-
- vds_dma_ok? PROC
- XPUSH <AX, CX, DX, SI>
- CALL es386?
- JNE vds_pse ; por si las moscas
- MOV AX,354Bh
- PUSH ES
- INT 21h ; ES:BX -> INT 4Bh
- MOV AX,ES
- POP ES
- OR AX,BX
- JZ vds_pse ; INT 4Bh indefinida
- CMP AX,0FFFFh
- JNE hay_vds?
- CMP BX,0FFFFh
- JE vds_pse ; INT 4Bh indefinida
- hay_vds?: MOV AX,8102h
- XOR DX,DX
- XOR SI,SI
- XOR DI,DI ; SI:DI a 0 por si acaso
- INT 4Bh
- JC vds_pse ; si no hay VDS...
- MOV AX,SI
- OR AX,DI
- JZ vds_pse ; no parece una VDS...
- CMP SI,0
- JE dma_s_ok
- MOV DI,0FFFFh ; con 64K nos basta
- dma_s_ok: CMP DI,tbuffer
- JAE vds_ok
- STC ; no basta el buffer
- XPOP <SI, DX, CX, AX>
- RET
- vds_pse: MOV BX,1234h ; retornar sin problemas
- MOV DI,0FFFFh
- vds_ok: CLC ; basta ese buffer
- XPOP <SI, DX, CX, AX>
- RET
- vds_dma_ok? ENDP
-
- ; ------------ Adaptar parámetros del programa si ya está instalado.
-
- adaptar_param PROC
- PUSH ES
- CMP instalado,ON
- JNE salir_adap ; aún no instalado
- MOV ES,tsr_seg
- CMP param_g,ON
- JNE param_dr?
- MOV AX,gaprw
- MOV ES:gaprw,AX
- param_dr?: CMP param_dron,ON
- JNE param_droff?
- MOV ES:drdos6,ON ; soporte DISKCOPY de DR-DOS
- param_droff?: CMP param_droff,ON
- JNE param_dwon?
- MOV ES:drdos6,OFF
- param_dwon?: CMP param_dwon,ON
- JNE param_dwoff?
- MOV ES:cachewr,ON ; caché escritura retardada
- param_dwoff?: CMP param_dwoff,ON
- JNE fin_adap
- MOV ES:cachewr,OFF
- fin_adap: MOV AX,tbase
- MOV ES:tbase,AX ; actualizar siempre esta cte
- salir_adap: POP ES
- RET
- adaptar_param ENDP
-
- ; ------------ Informar de las unidades empleadas y otras cuestiones.
-
- informe PROC
- PUSH ES
- MOV ES,tsr_seg
- MOV AL,ES:unidad_base ; primera letra unidad
- MOV BL,ES:info_E.unidad
- MOV BH,ES:info_E.tipo_drv ; datos A:
- MOV CL,ES:info_F.unidad
- MOV CH,ES:info_F.tipo_drv ; datos B:
- POP ES
-
- LEA DX,hay_2mgui_txt
- CALL print
-
- MOV nueva_u,AL
- ADD nueva_u,'A'
- informa_otra: MOV vieja_u,BL
- ADD vieja_u,'A'
- LEA DX,hay_en_txt
- CALL print
- LEA DX,nueva_u ; indicar nueva unidad
- CALL print
- MOV BL,BH
- DEC BL
- MOV BH,0
- SHL BX,1
- ADD BX,OFFSET t_drvs
- MOV DX,[BX]
- CALL print ; imprimir su tipo
- LEA DX,hay2_txt
- CALL print
- LEA DX,vieja_u
- CALL print ; imprimir letra física
-
- AND CH,CH
- JZ fin_informe ; no hay más unidades
- MOV BX,CX
- MOV CH,0
- INC nueva_u
- JMP informa_otra ; informar 2ª unidad
-
- fin_informe: PUSH ES ; *
- MOV ES,tsr_seg
- LEA DX,gap_txt
- CALL print
- MOV AX,ES:gaprw
- XOR DX,DX
- MOV CL,3
- CALL print_32 ; indicar el GAP
- LEA DX,dma1_txt
- CALL print
- CMP ES:modoDMA,ON
- JE modo_dma_ok
- LEA DX,dmano_txt
- CALL print
- modo_dma_ok: LEA DX,dma2_txt
- CALL print ; y el modo DMA
- CMP ES:ems_handle,0
- LEA DX,buffer_ems_txt
- JE modo_ems_ok
- CALL print
- modo_ems_ok: LEA DX,cache_off_txt
- CMP ES:cachewr,ON
- JE modo_cache_ok
- CALL print
- modo_cache_ok: LEA DX,sopdr_on_txt
- CMP ES:drdos6,ON
- JNE modo_dr_ok
- CALL print
- modo_dr_ok: POP ES ; *
- LEA DX,pet_ayuda_txt
- CALL print ; ... cómo pedir ayuda ...
- RET
- informe ENDP
-
- ; ------------ Formatear disquete 2MGUI.
-
- format_disk PROC
- CALL get_drv ; obtener unidad física
- JNC fmt_buen_drv
- OR errw,MALDRV
- JMP rep_fmt
- fmt_buen_drv: CALL init_flp ; preparar áreas de datos
- CALL init_boot ; construir sector de arranque
- CALL set_fat_buffer ; buffer para la FAT
- JNC fmt_buena_fat
- JMP rep_fmt ; no hay memoria para la FAT
- fmt_buena_fat: MOV errw,0
- MOV status,0 ; borrar errores previos
- CALL print_cabf ; mensaje de cabecera
- CMP param_k,ON
- JE format_ya ; opción /K: evitar pausa
- LEA DX,pausaf_txt
- CALL print
- MOV AH,8
- INT 21h ; pedir tecla
- AND AL,AL
- JNZ esa_tec
- MOV AH,8
- INT 21h ; tecla de doble código
- esa_tec: LEA DX,limpia_txt
- CALL print
- CMP AL,13
- JE format_ya
- JMP teclaESC? ; se pulsó ESC
- format_ya: STC
- CALL reset_drv
- MOV [SI].cilindro,0
- fmt_otro_cil: MOV [SI].cabezal,0 ; empezar en pista/cabeza 0
- fmt_otro_cab: MOV CX,4 ; reintentos
- JMP fmt_empieza
- fmt_repite: CLC
- CALL reset_drv
- fmt_empieza: CALL test_kb
- JNC fmt_proc
- JMP teclaESC?
- fmt_proc: CALL print_cc ; imprimir nº cilindro/cabezal
- CALL genera_infof
- CALL motor_ok
- CALL seek_drv
- LEA DX,f_txt ; [F--]
- CALL print
- CALL formatea_pista
- CALL test_err ; ¿error?
- JNC fmt_wr?
- JMP rep_fmt
- fmt_wr?: JNZ fmt_wr
- LOOP fmt_repite ; reintentos
- JMP marca_pista ; pista defectuosa
- fmt_wr: CMP [SI].cilindro,1
- CMC
- CALL init_buffer ; buffer a 0 en cilindro 0
- LEA DX,w_txt
- CALL print ; [-X-]
- CALL escribe_pista
- CALL fix_err ; detectar capacidad excesiva
- CALL test_err ; ¿error?
- JC rep_fmt
- JNZ fmt_vr
- LOOP fmt_repite ; reintentos
- JMP marca_pista ; pista defectuosa
- fmt_vr: CMP [SI].cilindro,2
- JB si_verificar ; verificar siempre pistas 0-1
- CMP param_n,ON
- JE fmt_inc_cab ; verificación desactivada
- si_verificar: CALL test_kb
- JC teclaESC?
- LEA DX,v_txt
- CALL print ; [--V]
- CALL lee_pista
- CALL fix_err ; detectar capacidad excesiva
- CALL test_err ; ¿error?
- JC rep_fmt
- JNZ fmt_inc_cab
- LOOP fmt_repite
- JMP marca_pista ; pista defectuosa
- fmt_inc_cab: INC [SI].cabezal
- CMP [SI].cabezal,1
- JA fmt_inc_cil
- JMP fmt_otro_cab ; a por otro cabezal...
- fmt_inc_cil: INC [SI].cilindro
- MOV AL,[SI].cilindro
- CMP AL,2
- JB fmt_lento
- CMP param_q,ON
- JE fin_fmt ; opción /Q
- fmt_lento: CMP AL,maxpistas
- JAE fin_fmt
- JMP fmt_otro_cil ; a por otro cilindro ...
- teclaESC?: CMP AX,1000h
- JE fin_fmt ; Quickformat
- OR errw,ABORTADO
- JMP rep_fmt
- marca_pista: CMP [SI].cilindro,0 ; ¿no puede ni con la primera?
- JE rep_fmt ; mal asunto, es la del sistema
- CALL marcar_fat
- JMP fmt_inc_cab ; marcar esa pista y a por otra
- fin_fmt: CALL init_disk
- rep_fmt: CLC
- CALL motor_off_cnt ; cuenta normal detención motor
- CALL info_fmt
- TEST errw,MALDRV OR MUCHAFAT OR ABORTADO
- JNZ format_fin ; fin total del proceso
- CMP param_k,ON
- JE format_fin ; con /K sólo un disco
- JMP format_disk ; formatear más discos
- format_fin: RET
- format_disk ENDP
-
- ; ------------ Comprobar si se pulsa ESC y limpiar buffer.
-
- test_kb PROC
- MOV AH,1
- INT 16h
- JZ no_ESC ; no quedan teclas en el buffer
- MOV AH,0
- INT 16h
- CMP AL,27
- JE si_ESC ; tecla ESC
- CMP AX,1000h
- JE si_ESC ; ALT-Q
- JMP test_kb
- si_ESC: STC
- RET
- no_ESC: CLC
- RET
- test_kb ENDP
-
- ; ------------ Si da error de unidad no preparada al escribir o al
- ; verificar en la primera pista y no lo dio al formatear,
- ; es que se pide más capacidad de la soportada.
-
- fix_err PROC
- TEST status,80h
- JZ fix_err_r
- CMP [SI].cilindro,0
- JNE fix_err_r ; si no es cilindro 0, vale
- MOV status,7Fh
- fix_err_r: RET
- fix_err ENDP
-
- ; ------------ Comprobar categoría del error. Los errores fatales
- ; provocan el final inmediato del formateo.
-
- test_err PROC
- CMP status,0
- JE err_none
- CMP status,3 ; ¿protegido contra escritura?
- JE err_fatal
- TEST status,80h ; ¿no preparada?
- JNZ err_fatal
- CMP SP,SP
- CLC
- RET ; ZF=1 y CF=0 -> error "venial"
- err_none: CMP SP,0
- CLC
- RET ; ZF=0 y CF=0 -> sin error
- err_fatal: CMP SP,SP
- STC
- RET ; ZF=1 y CF=1 -> error grave
- test_err ENDP
-
- ; ------------ Poner el buffer de pista con valores de test. A la
- ; entrada, CF=0 selecciona un buffer lleno de ceros
- ; y CF=1 lleno de una secuencia aleatoria predecible.
-
- init_buffer PROC
- PUSH ES
- XPUSH <AX, BX, CX>
- MOV ES,sbuffer
- MOV BX,0
- JC buffer_rnd
- CALL tpistaAX
- MOV CX,AX
- fill_pis0: MOV BYTE PTR ES:[BX],0
- INC BX
- LOOP fill_pis0 ; buffer a 0
- JMP buff_init
- buffer_rnd: CALL tpistaAX
- MOV CX,AX
- MOV semilla,1 ; nº aleatorios predecibles
- fill_pisx: CALL rnd
- MOV BYTE PTR ES:[BX],AL
- INC BX
- LOOP fill_pisx ; buffer con patrón aleatorio
- buff_init: XPOP <CX, BX, AX>
- POP ES
- RET
- init_buffer ENDP
-
- ; ------------ Imprimir cabecera de formateo.
-
- print_cabf PROC
- XPUSHA
- LEA DX,fmtm1_txt
- CALL print ; "Formateando ..."
- MOV AL,[SI].infb.mfrontera
- MOV AH,0
- MUL [SI].infb.tpista1
- MOV BX,DX
- MOV CX,AX ; BX:CX bytes hasta FRONTERA
- MOV AL,maxpistas
- SUB AL,[SI].infb.mfrontera
- MOV AH,0
- MUL [SI].infb.tpista2 ; DX:AX bytes tras FRONTERA
- ADD AX,CX
- ADC DX,BX ; bytes totales por cara
- MOV CL,maxpistas
- MOV CH,0
- DIV CX ; bytes por pista
- XOR DX,DX
- MOV CL,7+16
- PUSH AX ; *
- CALL print_32 ; imprimir bytes por pista
- LEA DX,fmtm2_txt
- CALL print
- MOV DL,disquetera
- ADD DL,'A'
- MOV AH,2
- INT 21h ; imprimir unidad
- LEA DX,fmtm3_txt
- CALL print
- MOV DL,[SI].unidad
- CALL tipo_disco ; tipo de la unidad
- DEC BL
- MOV BH,0
- SHL BX,1
- ADD BX,OFFSET t_drvs
- MOV DX,[BX]
- CALL print ; imprimir tipo
- LEA DX,fmtm4_txt
- CALL print
- LEA DX,fmtm5_txt
- CALL print
- CALL print_dsk_tipo ; imprimir tipo del disquete
- LEA DX,fmtm6_txt
- CALL print
- POP AX ; * bytes por pista
- MOV BL,maxpistas
- MOV BH,0
- SHL BX,1 ; pore las dos caras
- MUL BX ; DX:AX bytes en disco
- MOV BX,1024
- DIV BX ; AX Kbytes
- XOR DX,DX
- MOV CL,6+16
- CALL print_32 ; imprimir Kbytes
- LEA DX,fmtm7_txt
- CALL print
- XPOPA
- RET
- print_cabf ENDP
-
- ; ------------ Imprimir el tipo del disquete en uso.
-
- print_dsk_tipo PROC
- MOV DL,[SI].unidad
- CALL tipo_disco ; tipo de la unidad
- MOV BH,BL
- CMP BL,5
- JB ted_no
- MOV BL,4 ; en 2.88M por defecto 1.44M
- ted_no: MOV AL,param_dd
- OR AL,param_dh
- CMP AL,OFF
- JE tdd_ok
- DEC BL ; disco DD
- tdd_ok: CMP param_ed,ON
- JNE ted_ok
- CMP BH,5
- JNE ted_ok
- MOV BL,5 ; disco 2.88M
- ted_ok: DEC BL
- MOV BH,0
- SHL BX,1
- ADD BX,OFFSET t_drvs
- MOV DX,[BX]
- CALL print ; imprimir tipo
- RET
- print_dsk_tipo ENDP
-
- ; ------------ Imprimir nº cilindro y cabezal.
-
- print_cc PROC
- XPUSHA
- LEA DX,cil_txt
- CALL print
- MOV AL,[SI].cilindro
- CALL print_8
- LEA DX,cab_txt
- CALL print
- MOV AL,[SI].cabezal
- CALL print_8
- LEA DX,p_txt
- CALL print
- XPOPA
- RET
- print_cc ENDP
-
- ; ------------ Establecer buffer para la FAT.
-
- set_fat_buffer PROC
- MOV AX,fbuffer
- AND AX,AX
- JNZ haymemfat ; ya había memoria asignada
- MOV AX,bsectfat
- MOV BX,[SI].bytes_sector
- MUL BX ; sectfat * tamaño sector
- MOV CL,4
- SHR AX,CL ; bytes -> párrafos
- MOV BX,AX
- MOV AH,48h
- PUSH BX
- INT 21h ; pedir memoria
- POP BX
- JNC haymemfat
- OR errw,MUCHAFAT ; no hay memoria suficiente
- STC
- RET
- haymemfat: MOV fbuffer,AX
- PUSH ES ; *
- MOV ES,AX
- XOR DI,DI
- MOV AX,bsectfat
- MUL [SI].bytes_sector ; sectores -> bytes
- SHR AX,1 ; palabras
- MOV CX,AX
- SUB CX,2 ; saltar dos primeras palabras
- MOV AL,media_id
- CLD
- STOSB ; byte de medios
- MOV AX,0FFFFh
- STOSW ; otros dos bytes
- MOV AL,0
- CMP tipofat,12
- JE init_fat4
- DEC AL
- init_fat4: STOSB ; 0 (FAT12) ó 0FFh (FAT16)
- XOR AX,AX
- REP STOSW ; poner resto de FAT a 0
- POP ES ; *
- CLC
- RET
- set_fat_buffer ENDP
-
- ; ------------ Marcar pista defectuosa en la FAT.
-
- marcar_fat PROC
- MOV AL,[SI].cilindro
- SHL AL,1
- ADD AL,[SI].cabezal ; AX pistas hasta la frontera
- MOV AH,0
- MOV CX,0 ; CX pistas desde la frontera
- MOV BL,[SI].infb.mfrontera
- SHL BL,1
- CMP AL,BL
- JBE dispis_ok
- MOV CL,AL
- MOV AL,BL ; hay cruce de frontera
- SUB CL,AL
- dispis_ok: MUL [SI].infb.tpista1
- XPUSH <DX, AX>
- MOV AX,CX
- MUL [SI].infb.tpista2 ; DX:AX = bytes tras frontera
- XPOP <BX, CX> ; CX:BX = bytes antes frontera
- ADD AX,BX
- ADC DX,CX ; offset al primer byte erróneo
- XPUSH <AX, DX>
- MOV CX,[SI].bytes_sector
- DIV CX
- MOV BX,AX ; BX = primer sector erróneo
- CALL tpistaAX
- MOV CX,AX ; tamaño pista
- XPOP <DX, AX>
- ADD AX,CX
- ADC DX,0
- MOV CX,[SI].bytes_sector
- DIV CX
- AND DX,DX
- JZ ultserr_ok
- INC AX ; AX = último sector erróneo
- ultserr_ok: SUB AX,BX
- MOV CL,bscluster
- MOV CH,0
- ADD AX,CX
- DEC AX
- XOR DX,DX
- DIV CX ; AX = clusters defectuosos
- DEC BX ; descontar BOOT
-
- PUSH AX
- MOV AX,32
- MUL brootdir
- DIV [SI].bytes_sector
- SUB BX,AX ; descontar ROOT
- POP AX
-
- MOV CL,bnfats
- MOV CH,0
- desc_fat: SUB BX,bsectfat
- LOOP desc_fat ; descontar FAT(s)
- XCHG AX,BX ; AX=primer sector, BX=nºclusters
- XOR DX,DX
- MOV CL,bscluster
- DIV CX ; AX = primer cluster
- ADD AX,2 ; se numeran desde 2
- MOV CX,BX
- marcar: CALL badpoke_fat ; marcar cluster erróneo
- INC AX
- LOOP marcar
- RET
- marcar_fat ENDP
-
- ; --- Modificar una entrada en la FAT12 ó 16.
-
- badpoke_fat PROC
- XPUSH <DS, AX, BX, CX>
- MOV DS,fbuffer
- XOR BX,BX
- CMP CS:tipofat,16
- JE poke_fat16
- MOV DX,0FF7h ; cluster defectuoso
- CALL poke_fat12
- JMP fat_poked
- poke_fat16: SHL AX,1
- ADD BX,AX
- MOV WORD PTR DS:[BX],0FFF7h
- fat_poked: XPOP <CX, BX, AX, DS>
- RET
- badpoke_fat ENDP
-
- ; --- Escribir un elemento en una FAT-12
- ; Entrada: AX = posición de dicho elemento
- ; DS:BX = FAT cargada en memoria
- ; DX = nuevo valor de dicho elemento
-
- poke_fat12 PROC
- PUSH AX ; preservar registros
- PUSH BX
- PUSH DX
- ADD BX,AX ; BX = BX + cluster
- SHR AX,1 ; AX = cluster / 2
- PUSHF ; CF = 1 si impar
- ADD BX,AX ; BX = BX + cluster * 1,5
- MOV AX,[BX] ; AX = palabra con dato 12 bits
- POPF
- JC poke_fat_imp
- AND AX,1111000000000000b ; preservar la otra entrada
- JMP poke_fat_ok
- poke_fat_imp: AND AX,0000000000001111b ; preservar la otra entrada
- PUSH CX
- MOV CL,4
- SHL DX,CL ; colocarlo: 4 bits a la izda
- POP CX
- poke_fat_ok: OR AX,DX ; «mezclar»
- MOV [BX],AX ; nuevo valor en la FAT
- POP DX
- POP BX
- POP AX
- RET ; retorno sin alterar registros
- poke_fat12 ENDP
-
- ; ------------ Inicializar BOOT y FAT (y ROOT si procede).
-
- init_disk PROC
- XPUSHA
- MOV [SI].cilindro,0
- MOV [SI].cabezal,0
- CLC
- CALL init_buffer ; buffer a 0
- MOV CX,[SI].bytes_sector
- XPUSH <ES, SI> ; *
- MOV ES,sbuffer
- XOR DI,DI
- LEA SI,sector_boot
- CLD
- REP MOVSB ; crear BOOT
- XPOP <SI, ES> ; *
- CLC
- CALL reset_drv
- CALL motor_ok
- CALL seek_drv
- CALL escribe_pista ; grabar a bajo nivel el BOOT
- CMP status,0
- JNE fallo_init
-
- PUSH ES
- MOV ES,tsr_seg
- MOV ES:[SI].cambiodisco,ON ; simular cambio de disco
- POP ES
-
- MOV DL,disquetera
- INC DL
- MOV AH,32h
- PUSH DS
- INT 21h ; forzar acceso a disco usando
-
- POP DS ; ya el sistema operativo
- MOV AL,disquetera
- XOR BX,BX
- MOV CX,bsectfat ; sectores en FAT
- MOV DX,1
- PUSH DS ; *
- MOV DS,fbuffer
- CALL int26h ; grabar FAT1
- POP DS ; *
- JC fallo_init ; fallo al escribir FAT
- CMP bnfats,1
- JE init_root ; sólo una FAT (CF=0)
- XOR BX,BX
- MOV CX,bsectfat
- MOV DX,CX
- INC DX ; saltar FAT1 + BOOT
- MOV AL,disquetera
- PUSH DS ; *
- MOV DS,fbuffer
- CALL int26h ; grabar FAT2
- POP DS ; *
- JNC init_root
- fallo_init: OR errw,MALSYS ; fallo en áreas del sistema
- JMP fin_init
- init_root: MOV BX,ptr_label
- AND BX,BX
- JNZ tetiq_ok
- MOV BX,ptr_ilabel
- AND BX,BX
- JZ fin_init ; no hay etiqueta de volúmen
- tetiq_ok: CLC
- CALL init_buffer ; buffer a 0
- CALL copia_etiq
- CMP BX,ptr_ilabel
- JNE wr_root
- CALL inc_etiq
- wr_root: MOV CX,bsectfat
- MOV AL,bnfats
- MOV AH,0
- MUL CX
- INC AX ; primer sector directorio raíz
- MOV DX,AX
- MOV CX,1
- MOV AL,disquetera
- PUSH DS ; *
- MOV DS,sbuffer
- XOR BX,BX
- CALL int26h ; grabar ROOT
- POP DS
- fin_init: XPOPA
- RET
- init_disk ENDP
-
- ; ------------ Como el MS-DOS 7 de Windows 95 (beta 2) no deja usar
- ; la INT 26h, se graba por IOCTL :-)
-
- int26h PROC
- XPUSHA
- PUSH ES
- MOV ES,ES:tsr_seg
- MOV AH,ES:drdos6
- MOV ES:drdos6,OFF ; anular emulación DR-DOS
- MOV SI,1 ; con caché: CX operaciones
- CMP ES:cachewr,ON
- MOV SI,CX ; sin caché: una operación
- JE nsi26ok
- nsi26ok: POP ES
- i26_buc: XPUSH <AX, BX, CX, DX, SI, DS> ; * (preservar emulacion)
- LEA DI,buffer_aux
- MOV BYTE PTR ES:[DI],0
- MOV WORD PTR ES:[DI+1],0 ; cabezal
- MOV WORD PTR ES:[DI+3],DX ; primer cilindro
- MOV WORD PTR ES:[DI+5],0 ; primer sector
- MOV WORD PTR ES:[DI+7],SI ; nº sectores
- MOV WORD PTR ES:[DI+9],BX
- MOV WORD PTR ES:[DI+11],DS ; dirección
- INC AX
- MOV BL,AL ; unidad
- MOV AX,440Dh
- MOV CX,841h ; escribir pista
- MOV DX,DI
- PUSH ES
- POP DS
- INT 21h
- XPOP <DS, SI, DX, CX, BX, AX> ; *
- JC i26_fallo
- ADD BX,ES:boot_tsect
- INC DX
- SUB CX,SI
- JNZ i26_buc
- CLC
- i26_fallo: PUSH ES
- MOV ES,ES:tsr_seg ; cuidado con flags :-)
- MOV ES:drdos6,AH ; restaurar emulación DR-DOS
- POP ES
- XPOPA
- RET
- int26h ENDP
-
- ; --- Crear etiqueta de volúmen (psp:BX -> sbuffer:0)
-
- copia_etiq PROC
- XPUSHA
- XPUSH <ES, DS>
- CLD
- MOV ES,sbuffer
- XOR DI,DI
- MOV DS,psp
- MOV SI,BX
- MOV CX,11
- JCXZ nom_et_cp
- genera_et: LODSB
- CMP AL,' '
- JE completa_et
- CMP AL,9
- JE completa_et
- CMP AL,'/'
- JE completa_et
- CMP AL,13
- JE completa_et
- STOSB
- LOOP genera_et
- JMP nom_et_cp
- completa_et: MOV AL,' '
- STOSB
- LOOP completa_et
- nom_et_cp: MOV BYTE PTR ES:[11],28h
- POP DS
- MOV WORD PTR ES:[22],2048 ; 1:00
- MOV WORD PTR ES:[24],7745 ; 1/2/95
- LEA DX,null
- MOV AX,3D00h
- MOV CX,0
- INT 21h ; abrir fichero "NUL"
- JC fin_cpet
- MOV BX,AX
- MOV AX,5700h
- PUSH BX
- INT 21h ; consultar su fecha/hora
- POP BX
- JC fin_cpetcf
- MOV AX,CX
- OR AX,DX
- JZ fin_cpetcf
- MOV WORD PTR ES:[22],CX ; hora
- MOV WORD PTR ES:[24],DX ; fecha
- fin_cpetcf: MOV AX,3E00h
- INT 21h ; cerrar fichero "NUL"
- fin_cpet: POP ES
- XPOPA
- RET
- copia_etiq ENDP
-
- ; --- Incrementar nº de etiqueta de volúmen.
-
- inc_etiq PROC
- PUSH DS
- MOV DS,psp
- MOV CX,16
- busca_fetq: MOV AL,[BX]
- CMP AL,' '
- JE fin_etq
- CMP AL,9
- JE fin_etq
- CMP AL,'/'
- JE fin_etq
- CMP AL,13
- JE fin_etq
- INC BX
- LOOP busca_fetq
- JMP etq_inc
- fin_etq: DEC BX
- MOV AL,[BX]
- CMP AL,'0'
- JB etq_inc
- CMP AL,'9'
- JA etq_inc
- INC AL
- CMP AL,'9'
- JA etq_p10
- MOV [BX],AL
- JMP etq_inc
- etq_p10: MOV BYTE PTR [BX],'0'
- JMP fin_etq
- etq_inc: POP DS
- RET
- inc_etiq ENDP
-
- ; ------------ Inicializar sector de arranque.
-
- init_boot PROC
- MOV AL,[SI].infb.vunidad2
- MOV bootp.vunidad2,AL
- MOV AH,frontera ; disco dividido en dos mitades
- CMP AL,[SI].vunidad1
- JNE init_fr
- MOV AH,maxpistas ; disco uniforme
- init_fr: MOV bootp.mfrontera,AH
- MOV [SI].infb.mfrontera,AH
- MOV AX,bsectini
- MOV boot_tsect,AX ; tamaño de sector usado
- MOV AX,tcluster
- XOR DX,DX
- DIV boot_tsect
- AND AL,AL
- JNZ init_sc
- INC AL
- init_sc: MOV bscluster,AL ; sectores por cluster
- MOV AL,nfats
- MOV bnfats,AL ; número de FATs
-
- MOV AX,32
- MUL rootdir
- DIV boot_tsect
- AND DX,DX
- JZ bdir_ok
- INC AX
- bdir_ok: MOV srootdir,AX ; entradas raíz llenando sectores
- MUL boot_tsect
- MOV CX,32
- DIV CX
- MOV brootdir,AX ; nº entradas ajustado
-
- MOV AX,[SI].infb.tpista2
- MOV bootp.tpista2,AX
- MOV AX,[SI].infb.tpista1
- MOV bootp.tpista1,AX
- MOV BL,bootp.mfrontera
- MOV BH,0
- SHL BX,1
- MUL BX
- MOV CX,DX
- MOV BX,AX ; CX:BX bytes primera parte disco
- MOV AL,maxpistas
- SUB AL,[SI].infb.mfrontera
- MOV AH,0
- SHL AX,1
- MUL bootp.tpista2 ; DX:AX bytes segunda parte disco
- ADD AX,BX
- ADC DX,CX ; DX:AX bytes totales en el disco
- DIV boot_tsect
- MOV bsectores,AX ; AX = número de sectores
-
- DEC AX ; calcular FAT...
- SUB AX,srootdir ; AX = sect tot - 1 boot - N raíz
- MOV CX,AX
- MOV AL,bscluster
- MOV AH,0
- SHL AX,1
- MUL boot_tsect ; bytes_sect * sect_cluster * 2
- MOV BX,3 ; 1.5 * 2 = 3 (FAT12)
- DIV BX
- ADD AL,bnfats
- ADC AH,0
- XCHG AX,CX
- XOR DX,DX
- DIV CX ; AX = sectores ocupados por FAT12
- AND DX,DX
- JZ f12_ok
- INC AX
- f12_ok: MOV bsectfat,AX ; sectores en FAT12
- MOV tipofat,12 ; supuesta FAT-12
- ADD AX,srootdir
- INC AX
- SUB AX,bsectores ; (fat+root+1) - sectores totales
- NEG AX ; resta al revés
- XOR DX,DX
- MOV CL,bscluster
- MOV CH,0
- DIV CX ; AX = nº clusters
- CMP AX,4085
- JB boot_dir ; en efecto, la FAT es de 12
-
- MOV AX,bsectores
- DEC AX ; calcular FAT...
- SUB AX,srootdir ; AX = sect tot - 1 boot - N raíz
- MOV CX,AX
- MOV AL,bscluster
- MOV AH,0
- SHL AX,1
- MUL boot_tsect ; bytes_sect * sect_cluster * 2
- MOV BX,4 ; 2 * 2 = 4 (FAT16)
- DIV BX
- ADD AL,bnfats
- ADC AH,0
- XCHG AX,CX
- XOR DX,DX
- DIV CX ; AX = sectores ocupados por FAT12
- AND DX,DX
- JZ f16_ok
- INC AX
- f16_ok: MOV bsectfat,AX ; sectores en FAT16
- MOV tipofat,16
- MOV BYTE PTR ftipo+4,'6'
- boot_dir: MOV AL,bnfats
- MOV AH,0
- MUL bsectfat ; sectores ocupados por FATs
- INC AX ; más BOOT
- ADD AX,srootdir ; más ROOT
- SUB AX,bsectores
- NEG AX ; sectores totales - ocupados
- MOV BL,bscluster
- MOV BH,0
- XOR DX,DX
- DIV BX ; DX = sectores redundantes
- MOV AX,boot_tsect
- MUL DX
- MOV BX,32
- DIV BX
- ADD brootdir,AX ; aprovecharlos para engordar ROOT
- CMP brootdir,240
- JBE boot_ok
- MOV brootdir,240 ; pero sin pasarse
- boot_ok: CALL rnd
- MOV WORD PTR bserie,AX ; inicializar nº serie
- CALL rnd
- MOV WORD PTR bserie+2,AX
- RET
- init_boot ENDP
-
- ; ------------ Informe del formateo.
-
- info_fmt PROC
- CALL pr_error ; posible mensaje de error
- JNC cont_info_fmt
- RET
- cont_info_fmt: LEA DX,capacidad1_txt
- CALL print
- MOV AX,bsectores
- MOV CX,[SI].bytes_sector
- MUL CX
- MOV CL,10+16
- CALL print_32 ; capacidad cruda en bytes
- LEA DX,capacidad2_txt
- CALL print
- MOV AX,ptr_label
- OR AX,ptr_ilabel
- JZ no_etiq
- LEA DX,etiq_txt
- CALL print
- MOV CX,11
- XOR BX,BX
- PUSH DS
- MOV DS,sbuffer
- pr_etq: MOV AH,2
- MOV DL,[BX]
- XPUSH <BX, CX>
- INT 21h
- XPOP <CX, BX>
- INC BX
- LOOP pr_etq
- POP DS
- LEA DX,crlf_txt
- CALL print
- no_etiq: MOV AX,brootdir
- XOR DX,DX
- MOV CL,11+16
- CALL print_32 ; entradas en directorio raíz
- LEA DX,if1_txt
- CALL print
- MOV AH,36h
- MOV DL,disquetera
- INC DL
- INT 21h ; obtener espacio en disco
- CMP AX,-1
- JNE info_espacio
- LEA DX,err_info_txt
- CALL print
- RET
- info_espacio: XPUSH <AX, BX, CX, DX>
- MOV AX,DX
- XOR DX,DX
- MOV CL,11+16
- CALL print_32 ; número de clusters
- LEA DX,if2_txt
- CALL print
- XPOP <DX, CX, BX, AX>
- XPUSH <AX, BX, CX, DX>
- MUL CX
- MOV CL,11+16
- CALL print_32 ; bytes por cluster
- LEA DX,if3_txt
- CALL print
- XPOP <DX, CX, BX, AX>
- XPUSH <AX, BX, CX, DX>
- MOV BX,DX
- MUL CX
- MUL BX
- MOV CL,11+16
- CALL print_32 ; bytes totales
- LEA DX,if4_txt
- CALL print
- XPOP <DX, CX, BX, AX>
- XPUSH <AX, BX, CX, DX>
- SUB DX,BX
- MOV BX,DX
- MUL CX
- MUL BX
- MOV CL,11+16
- CALL print_32 ; bytes defectuosos
- LEA DX,if5_txt
- CALL print
- XPOP <DX, CX, BX, AX>
- MUL CX
- MUL BX
- MOV CL,11+16
- CALL print_32 ; bytes libres
- LEA DX,if6_txt
- CALL print
- RET
- info_fmt ENDP
-
- ; ------------ Imprimir errores de trabajo.
-
- pr_error PROC
- LEA DX,limpia_txt
- CALL print
- CALL get_err_crit
- TEST errw,0FFFFh
- JNZ errorfmt
- CLC ; no hubo error
- RET
- errorfmt: LEA DX,no_2mgui_txt
- TEST errw,MALDRV
- JZ errorfmt2?
- CALL print ; la unidad no es 2MGUI
- errorfmt2?: LEA DX,abortado_txt
- TEST errw,ABORTADO
- JZ errorfmt3?
- CALL print ; formateo abortado
- errorfmt3?: LEA DX,no_prep_txt
- TEST errw,NOPREP
- JZ errorfmt4?
- CALL print ; unidad no preparada
- errorfmt4?: LEA DX,err_prot_txt
- TEST errw,PROTESCR
- JZ errorfmt5?
- CALL print ; protegida contra escritura
- errorfmt5?: LEA DX,mal_dens_txt
- TEST errw,MALADENS
- JZ errorfmt6?
- CALL print ; densidad incorrecta
- errorfmt6?: LEA DX,mal_sys_txt
- TEST errw,MALSYS
- JZ errorfmt7?
- CALL print ; fallo en áreas del sistema
- errorfmt7?: LEA DX,mucha_fat_txt
- TEST errw,MUCHAFAT
- JZ errorfmt8?
- CALL print ; FAT demasiado grande
- errorfmt8?: LEA DX,mucha_pis_txt
- TEST errw,MUCHAPISTA
- JZ errorfmt9?
- CALL print ; tamaño de pista no soportado
- errorfmt9?: STC ; hubo error
- RET
- pr_error ENDP
-
- ; ------------ Obtener error fatal.
-
- get_err_crit PROC
- CMP status,0
- JNE hay_crit?
- RET
- hay_crit?: MOV AX,NOPREP
- TEST status,80h
- JZ err2?
- OR errw,AX ; unidad no preparada
- RET
- err2?: MOV AX,PROTESCR
- CMP status,3
- JNE err7f?
- OR errw,AX ; protegida contra escritura
- RET
- err7f?: MOV AX,MUCHAPISTA
- CMP status,7Fh
- JNE err3
- OR errw,AX ; tamaño de pista no soportado
- RET
- err3: OR errw,MALADENS ; otro caso: mala densidad
- RET
- get_err_crit ENDP
-
- ; ------------ Test de capacidad máxima soportada y velocidad de
- ; rotación.
-
- test_disk PROC
- CALL get_drv
- CALL init_flp ; preparar áreas de datos
-
- MOV gaprw,-1 ; rutinas E/S en modo test
- MOV [SI].infb.mfrontera,86
-
- LEA DX,test_txt1
- CALL print
- LEA DX,lin_txt
- CALL print ; mensajes de cabecera
- MOV AL,[SI].unidad
- CALL drvfloppy?
- JNC test_drvok
- LEA DX,mal_unidad_txt
- CALL print
- JMP test_ret ; unidad incorrecta
- test_drvok: CMP param_dh,ON
- JNE test_drvAL
- LEA DX,dh_test_txt
- CALL print
- JMP test_ret ; parámetro /DH en test
- test_drvAL: CMP param_nodma,OFF
- JE test_posible
- CMP pcxt,OFF
- JE test_posible
- LEA DX,errxtdma_txt
- CALL print
- JMP test_ret ; PC/XT: sólo vale con DMA
- test_posible: LEA DX,test_txt_t
- CALL print
- MOV AH,0
- INT 16h ; pausa inicial
- LEA DX,limpia_txt
- CALL print
- CMP AL,27
- JNE hacer_test
- test_esc: LEA DX,limpia_txt ; cancelado con ESC
- CALL print
- LEA DX,test_esc_txt
- CALL print
- JMP test_ret
- hacer_test:
- MOV modoDMA,ON ; supuesto con DMA
- CMP param_nodma,ON
- JNE haz_test
- MOV modoDMA,OFF ; pues es sin él
-
- MOV tmodo,0 ; primer test con bits iguales
-
- haz_test: CMP modoDMA,OFF
- JE aviso_sincero
- CALL vds_dma_ok?
- MOV AX,14*1024 ; buffer DMA para 1.44M
- CMP [SI].tsector,7
- JE tdok
- MOV AX,28*1024 ; buffer DMA para 2.88M
- tdok: CMP DI,AX
- JAE otro_test
- LEA DX,test_bdma_txt
- CALL print
- JMP otro_test
-
- aviso_sincero: LEA DX,test_dma_txt
- CALL print
-
- otro_test: CALL test_pista
- JC test_fatal ; fallo grave (protegido, etc).
- CMP status,1
- JNE test_prosigue ; no hay tecla ESC
- LEA DX,limpia_txt ; cancelado con ESC
- CALL print
- LEA DX,test_esc_txt
- CALL print
- JMP ret_cam_test
-
- test_prosigue: CMP status,2
- JNE test_info
- CALL pr_error ; mala densidad
- JMP ret_cam_test
- test_fatal: CALL pr_error ; imprimir error trágico
- JMP ret_cam_test
- test_info: LEA DX,limpia_txt
- CALL print
- LEA DX,test_r_txt11c ; información de resultados
- CMP modoDMA,ON
- JE tif1
- LEA DX,test_r_txt11s
- tif1: CALL print ; con/sin DMA
- LEA DX,test_r_txt12
- CALL print
- LEA DX,test_r_txt12i
- CMP tmodo,0
- JE tif2
- LEA DX,test_r_txt12d
- tif2: CALL print ; bits idénticos/aleatorios
- LEA DX,test_r_txt13
- CALL print
- MOV AX,bytes_ok
- SUB AX,SYSBYTES
- XOR DX,DX
- MOV CL,6+16
- CALL print_32 ; bytes soportados
- LEA DX,test_r_txt14
- CALL print
- CMP AX,[SI].infb.tpista2
- JAE pr_test_res
- CMP modoDMA,OFF
- JE pr_test_res ; no decir bobadas en NO-DMA
-
- PUSH AX
- MOV AX,243
- MUL [SI].infb.tpista2
- MOV DH,AH
- XCHG DH,DL ; DX = 95% de tpista2
- POP AX
-
- CMP AX,DX
- JAE info_maldrv ; diferencia modesta
- LEA DX,disco_def_txt
- CALL print ; ¡lo que casca es el disco!
- JMP gap_bien
-
- info_maldrv: LEA DX,test_res_mal
- CALL print ; unidad pésima
- pr_test_res: LEA DX,test_r_txt15
- CALL print
- MOV AX,bytes_max
- SUB AX,bytes_ok
- XOR DX,DX
- MOV CL,6+16
- CALL print_32 ; imprimir GAP mínimo
- LEA DX,test_r_txt14
- CALL print
-
- CMP AX,GAPDEF
- JBE gap_bien
- CMP AX,255
- JA gap_bien ; no decir bobadas si es raro
- CMP modoDMA,OFF
- JE gap_bien ; no decir bobadas en NO-DMA
- LEA DX,aviso_gap_txt
- CALL print
-
- gap_bien: INC tmodo
- CMP tmodo,1
- JA no_mas_test
- JMP otro_test ; test con bits aleatorios
-
- no_mas_test: LEA DX,test_res_txt3
- CALL print
- CALL spin_disk ; velocidad rotación
- ret_cam_test: CMP instalado,ON
- JNE test_ret_cam ; programa no residente
- PUSH ES
- MOV ES,tsr_seg
- MOV ES:[SI].controldrv,ON
- MOV ES:[SI].cambiodisco,ON ; simular cambio de disco
- POP ES
- test_ret_cam: CMP status,3
- JE test_ret ; salvo protegido de escritura...
- TEST status,80h
- JNZ test_ret ; o unidad no preparada...
- LEA DX,disco_mal_txt
- CALL print ; recordar disco dañado
- test_ret: CLC
- CALL motor_off_cnt ; cuenta normal detención motor
- RET
- test_disk ENDP
-
- ; --- Determinar la capacidad de la pista.
-
- test_pista PROC
- MOV bytes_ok,0 ; supuesto ninguno
- MOV AX,tpistamax1
- SHL AX,1 ; AX = tpistamax1 * 2
- MOV tmax,AX
- MOV CL,3
- SHR AX,CL ; AX = tpistamax1 / 4
- ADD tmax,AX ; máximo posible (tmax+tmin)/2
- MOV tmin,0 ; mínimo posible
- MOV iter,16 ; como mucho, 16 test
- STC
- CALL reset_drv
- nuevo_test: CALL test_kb
- JNC test_proc
- JMP test_abortado ; se pulsó ESC
- test_proc: MOV status,0
- MOV [SI].cilindro,0
- MOV [SI].cabezal,0
- LEA DX,test_txt2
- CALL print ; mensaje de "Probando..."
- MOV AX,tmax
- ADD AX,tmin
- SHR AX,1
- MOV [SI].infb.tpista1,AX ; tamaño de prueba
- CMP AX,1500
- JAE test_cont
- JMP test_mal_dens ; aquí pasa algo raro
- test_cont: CALL info_bytes
- CALL motor_ok
- CALL seek_drv
- CALL genera_infof
- CALL formatea_pista ; 1º intento formateo
- CMP status,0
- JE test_wr
- CALL formatea_pista ; 2º intento formateo
- CMP status,0
- JNE fallo_test
- test_wr: CMP tmodo,1
- CMC ; CF==0 si tmodo==0
- CALL init_buffer
- CALL escribe_pista ; 1º intento escritura
- CMP status,0
- JE test_rd
- CALL escribe_pista ; 2º intento escritura
- CMP status,0
- JNE fallo_test
- test_rd: CMP tmodo,1 ; CF==1 si tmodo==0
- CALL init_buffer
- CALL lee_pista ; 1º intento lectura
- CALL cnt_pista
- CMP status,0
- JE exito_test
- CMP tmodo,1 ; CF==1 si tmodo==0
- CALL init_buffer
- CALL lee_pista ; 2º intento lectura
- CALL cnt_pista
- CMP status,0
- JNE fallo_test
- exito_test: MOV AX,[SI].infb.tpista1 ; funcionó...
- MOV bytes_max,AX
- MOV AX,tmax
- ADD AX,tmin
- SHR AX,1
- MOV tmin,AX ; ...subir límite mínimo
- JMP nuevo_test?
- fallo_test: CALL test_err ; falló...
- JC aborta_test ; fallo grave
- MOV AX,tmax
- ADD AX,tmin
- SHR AX,1
- MOV tmax,AX ; ...bajar límite máximo
- nuevo_test?: MOV status,0 ; borrar errores anteriores
- MOV AX,tmax
- CMP AX,tmin
- JBE exit_test
- DEC iter ; contador de intentos
- JZ exit_test
- JMP nuevo_test
- test_abortado: MOV status,1 ; indicar test abortado
- JMP exit_test
- test_mal_dens: MOV status,2 ; probablemente mala densidad
- exit_test: CLC
- RET
- aborta_test: STC
- RET
- test_pista ENDP
-
- ; --- Comprobar qué parte de la pista se ha leído bien.
-
- cnt_pista PROC
- XPUSH <ES, AX, BX, CX>
- MOV ES,sbuffer
- XOR BX,BX
- MOV CX,[SI].infb.tpista1
- CMP tmodo,0
- JE test0
- MOV semilla,1 ; bits aleatorios
- testx: CALL rnd ; nº "aleatorio" esperado
- CMP ES:[BX],AL
- JNE test_rt
- INC BX
- LOOP testx ; comprobar cuántos coinciden
- JMP test_rt
- test0: CMP BYTE PTR ES:[BX],0 ; bits idénticos
- JNE test_rt
- INC BX
- LOOP test0 ; comprobar cuántos coinciden
- test_rt: MOV AX,[SI].infb.tpista1
- SHR AX,1
- CMP CX,AX
- JA test_mal ; ni media pista bien leída
- MOV AX,[SI].infb.tpista1
- SUB AX,CX
- MOV bytes_ok,AX ; los que se han leído bien
- MOV status,0
- CLC
- JMP pista_tr
- test_mal: MOV status,2 ; necesaria al menos 1/2 pista
- STC
- pista_tr: XPOP <CX, BX, AX, ES>
- RET
- cnt_pista ENDP
-
- ; --- Informar de la capacidad en fase de test. A la
- ; entrada, AX = bytes por pista en prueba.
-
- info_bytes PROC
- XOR DX,DX
- MOV CL,6+16
- CALL print_32 ; capacidad en pruebas
- LEA DX,test_txt3
- CALL print
- MOV DL,disquetera
- ADD DL,'A'
- MOV AH,2
- INT 21h ; imprimir unidad
- LEA DX,test_txt4
- CALL print
- CALL print_dsk_tipo ; imprimir su tipo
- LEA DX,test_txt5
- CALL print ; códigos de retroceso
- RET
- info_bytes ENDP
-
- ; --- Calcular e imprimir la velocidad de rotación.
-
- spin_disk PROC
- PUSH ES
- MOV ES,sbuffer
- XOR DI,DI
- MOV BYTE PTR ES:[DI],1 ; 1 sector
- MOV BYTE PTR ES:[DI+1],2 ; de 512 bytes
- MOV BYTE PTR ES:[DI+2],0 ; cilindro 0
- MOV BYTE PTR ES:[DI+3],0 ; cabezal 0
- MOV BYTE PTR ES:[DI+4],0 ; sector 0
- MOV BYTE PTR ES:[DI+5],2 ; 512 bytes
- POP ES
- CLC
- CALL reset_drv
- CALL motor_ok
- CALL seek_drv
- CALL formatea_pista ; pista de pruebas
- CLC
- CALL reset_drv
- CALL motor_ok
- CALL seek_drv
- PUSH DS ; *
- MOV AX,350Eh
- INT 21h
- XPUSH <ES, BX> ; ** preservar INT 0Eh
- LEA DX,nueva_int23
- MOV AX,2523h
- INT 21h ; establecer nueva INT 23h
- LEA DX,nueva_irq6 ; (para evitar Ctrl-Break)
- MOV AX,250Eh
- INT 21h ; establecer nueva INT 0Eh
-
- IN AL,61h
- AND AL,0FDh ; inhibir sonido
- OR AL,1
- OUT 61h,AL
- MOV AL,10110100b
- OUT 43h,AL ; 8254: cnt2 byte bajo/alto
- MOV AL,0FFh
- DELAY
- OUT 42h,AL
- DELAY
- OUT 42h,AL ; cuenta 65535
- MOV cnt_l,0FFFFh
- MOV cnt_h,0
-
- LEA DX,spin0_txt
- CALL print ; cabecera
-
- MOV iter,0 ; prueba en curso
-
- repite_spin: CMP iter,10
- JBE calc_spin ; como mínimo, 10 test
- CALL test_kb
- JNC calc_spin
- JMP fin_spin
- calc_spin: MOV AL,01001010b ; comando de lectura de ID's
- CALL fdc_write
- JNC spin_b1
- JMP err_spin
- spin_b1: MOV AL,[SI].unidad
- MOV irq6,OFF ; bajar flag de interrupción
- CALL fdc_write ; byte 1 de la orden
-
- STC
- CALL motor_off_cnt ; evitar que se pare el motor
-
- CMP iter,4
- JB calc_rot ; no imprimir 4 primeros test
- LEA DX,spin1_txt
- CALL print
- PUSH SI ; *
- MOV SI,dif_l
- MOV DI,dif_h
- MOV AX,25000
- CALL mult32x16 ; resultado en DXDISI
- MOV AX,29829
- CALL divi48x15 ; 25000 / 29829 =
- XOR DX,DX ; = (1/1193180) * 1000000
- MOV AX,iter
- SUB AX,3 ; nº iteraciones efectivas
- CALL divi48x15
- MOV DX,DI
- MOV AX,SI
- POP SI ; *
- MOV cntms_h,DX
- MOV cntms_l,AX
- MOV CL,01100111b
- CALL print_32 ; imprimir milisegundos
- LEA DX,spin2_txt
- CALL print
- MOV AX,iter
- XOR DX,DX
- MOV CL,4
- CALL print_32 ; imprimir iteraciones
- LEA DX,spin3_txt
- CALL print
-
- calc_rot: MOV AX,cnt_l
- MOV DX,cnt_h
- MOV CX,37 ; timeout en 2 segundos
- espera_irq6: CMP irq6,ON
- JE llego_irq6
- MOV BX,AX
- MOV AL,10000100b
- OUT 43h,AL ; 8254: enclavar contador 2
- DELAY
- IN AL,42h
- XCHG AH,AL
- DELAY
- IN AL,42h
- XCHG AH,AL ; AX = nueva cuenta
- CMP AX,BX
- JBE espera_irq6
- INC DX
- LOOP espera_irq6
- JMP err_spin ; timeout
- llego_irq6: CMP iter,2
- JNE guarda_tm ; desechar 2 primeras pruebas
- XPUSH <AX, DX>
- MOV CX,65535
- SUB CX,AX
- MOV AX,65535
- MUL DX ; DX:AX clocks del 8254
- ADD AX,CX
- ADC DX,0
- MOV dif0_l,AX
- MOV dif0_h,DX ; valor inicial
- XPOP <DX, AX>
- guarda_tm: MOV cnt_l,AX
- MOV cnt_h,DX ; cuenta actual
-
- MOV AX,65535
- MUL DX
- MOV CX,65535
- SUB CX,cnt_l
- ADD AX,CX
- ADC DX,0 ; DX:AX clocks 8254 actuales
-
- SUB AX,dif0_l
- SBB DX,dif0_h
- MOV dif_l,AX
- MOV dif_h,DX ; tiempo transcurrido
-
- LEA BX,fdc_result
- MOV CX,7
- sect_rd_res: CALL fdc_read ; leyendo resultados
- MOV [BX],AL
- INC BX
- LOOP sect_rd_res
- TEST fdc_result,11000000b ; ¿error?
- JNZ err_spin
-
- INC iter
- CMP iter,1000
- JAE fin_spin ; no más de 1000 test
- JMP repite_spin
-
- fin_spin: XPOP <DX, DS> ; **1
- MOV AX,250Eh
- INT 21h ; restaurar INT 0Eh
- POP DS ; *1
- CALL informe_spin
- RET
- err_spin: XPOP <DX, DS> ; **2
- MOV AX,250Eh
- INT 21h ; restaurar INT 0Eh
- POP DS ; *2
- LEA DX,spine_txt
- CALL print ; indicar que hubo problemas
- RET
- spin_disk ENDP
-
- ; --- Nueva rutina de INT 0Eh.
-
- nueva_irq6 PROC
- PUSH AX
- MOV AL,20h
- OUT 20h,AL ; EOI
- POP AX
- MOV CS:irq6,ON ; indicar interrupción
- nueva_int23: IRET
- nueva_irq6 ENDP
-
- ; --- Informar sobre la calidad de la disquetera.
-
- informe_spin PROC
- LEA DX,spind_txt
- CALL print
- PUSH SI ; *
- MOV DX,cntms_h
- MOV AX,cntms_l
- MOV DI,3
- MOV SI,3392 ; DISI = 200000 (3½ HD)
- CMP DX,3
- JAE splim_ok
- CMP AX,52261
- JA splim_ok
- MOV DI,2
- MOV SI,35594 ; DISI = 166666 (5¼ HD)
- splim_ok: SUB AX,SI
- SBB DX,DI
- JNC spsign_ok
- ADD AX,SI
- ADC DX,DI
- XPUSH <AX, DX> ; signo '-'
- MOV DL,'-'
- MOV AH,2
- INT 21h
- XPOP <DX, AX>
- XPUSH <SI, DI>
- SUB SI,AX
- SBB DI,DX
- MOV AX,SI
- MOV DX,DI ; restado el pequeño del grande
- XPOP <DI, SI>
- STC
- spsign_ok: PUSHF ; ** preservar signo
- CMP DX,0
- JNE fallo_sp ; muy raro, demasiada diferencia
- CMP AX,5000
- JA fallo_sp ; muy raro, demasiada diferencia
- MOV CL,01100101b
- CALL print_32
- PUSH AX ; ***
- LEA DX,spinf1_txt
- CALL print
- MOV AX,SI
- MOV DX,DI
- MOV CL,01100111b
- CALL print_32
- LEA DX,spinf2_txt
- CALL print
- POP AX ; ***
- POPF ; **1 signo
- POP SI ; *1
- LEA BX,spinf_calidad
- JC busca_calidad ; unidad rápida
- XOR AX,AX ; las lentas siempre buenas ;-)
- busca_calidad: CMP AX,[BX]
- JB dicha_calidad
- CMP WORD PTR [BX],0
- JE dicha_calidad
- ADD BX,4
- JMP busca_calidad
- dicha_calidad: MOV DX,[BX+2]
- CALL print ; imprimir mensaje de calidad
- LEA DX,spinf3_txt
- CALL print
- RET
- fallo_sp: POPF ; **2
- POP SI ; *2
- LEA DX,spine_txt
- CALL print ; fallo del test
- RET
- informe_spin ENDP
-
- ; ------------ Rutina para dividir números de 48 por números de 15
- ; bits sin desbordamientos y con cociente de 48 bits.
- ; DXDISI/AX --> cociente en DXDISI y resto en AX.
- ; No se modifican otros registros. No se comprueba si
- ; el divisor es cero o excede los 15 bits.
-
- divi48x15 PROC
- PUSH BX
- PUSH CX
- XOR BX,BX
- MOV CX,49 ; rotar 49 veces
- divi48_15_cmp: CMP AX,BX
- JA divi48_nosub
- SUB BX,AX
- STC
- divi48_nosub: RCL SI,1
- RCL DI,1
- RCL DX,1
- PUSHF
- CMP CX,1
- JE divi48_resto ; ¡no rotar el resto al final!
- POPF
- RCL BX,1
- PUSHF
- divi48_resto: POPF
- LOOP divi48_15_cmp
- MOV AX,BX
- POP CX
- POP BX
- RET
- divi48x15 ENDP
-
- ; ------------ Obtener la unidad física correspondiente a la unidad
- ; 2MGUI o a la indicada. Si la que se indica no es
- ; además 2MGUI, CF=1 a la vuelta.
-
- get_drv PROC
- MOV AL,disquetera
- CMP AL,-1
- JNE usar_esa
- MOV AL,0
- CMP instalado,ON
- JNE usar_esa ; la A: si no instalado
- PUSH ES
- MOV ES,tsr_seg
- MOV AL,ES:unidad_base ; por defecto la primera
- POP ES
- MOV disquetera,AL
- usar_esa: CALL drv2mgui?
- RET
- get_drv ENDP
-
- ; ------------ Comprobar si la unidad AL es 2MGUI y devolver en
- ; ese caso su número físico. AH corrompido.
-
- drv2mgui? PROC
- MOV AH,0
- CMP instalado,ON
- JNE drvn2mg ; si no instalado, no 2MGUI
- PUSH ES
- MOV ES,tsr_seg
- MOV AH,ES:unidad_base
- POP ES
- SUB AL,AH
- JZ drv2mg ; primera unidad 2MGUI
- CMP num_discos,1
- JE drvn2mg
- CMP AL,1
- JE drv2mg ; segunda unidad 2MGUI
- drvn2mg: ADD AL,AH
- STC
- RET
- drv2mg: MOV AH,info_E.unidad ; primera unidad
- AND AL,AL
- JZ drv2mg_ok
- MOV AH,info_F.unidad ; segunda unidad
- drv2mg_ok: MOV AL,AH
- CLC
- RET
- drv2mgui? ENDP
-
- ; ------------ Comprobar si la unidad AL es 2MGUI, A: ó B:
-
- drvfloppy? PROC
- CMP AL,1
- JA es2mgui? ; no es A: ni B:
- MOV DL,AL
- MOV AH,8
- MOV BL,0
- CALL tipo_disco ; tipo de la unidad
- CMP BL,2
- JE drvflp ; de alta densidad
- CMP BL,4
- JAE drvflp ; de alta densidad
- es2mgui?: CALL drv2mgui?
- RET
- drvflp: CLC
- RET
- drvfloppy? ENDP
-
- ; ------------ Inicializar datos para las rutinas de bajo nivel.
- ; A la entrada, AL = unidad física.
-
- init_flp PROC
- PUSH AX
- LEA SI,info_E ; apuntar a datos de la unidad
- MOV BX,GAPDEF
- MOV CL,modoDMA
- CMP instalado,ON
- JNE flpn_ok ; usar la primera si no reside
- PUSH ES
- MOV ES,tsr_seg
- MOV BX,ES:gaprw
- MOV CL,ES:modoDMA
- CMP AL,ES:info_E.unidad ; utilizar la correcta si el
- POP ES ; programa está residente
- JE flpn_ok
- LEA SI,info_F
- flpn_ok: MOV [SI].unidad,AL ; en adelante, la unidad física
- MOV gaprw,BX
- MOV modoDMA,CL ; GAP/modo DMA correcto
- CALL get_tpista
- MOV [SI].infb.tpista1,AX ; bytes por pista 1ª parte
- MOV [SI].infb.tpista2,BX ; bytes por pista 2ª parte
- MOV tpistamax1,CX ; bytes máximos teóricos 1ª parte
- MOV tpistamax2,DX ; bytes máximos teóricos 2ª parte
- MOV BL,7 ; log2 (16384) - 7 = 7
- CMP AX,16384
- JBE tsecf_ok
- INC BL ; log2 (32768) - 7 = 8
- tsecf_ok: MOV [SI].tsector,BL
- MOV AX,DI
- MOV [SI].vunidad1,AL
- MOV [SI].infb.vunidad2,AH
- MOV AX,bsectini
- MOV [SI].bytes_sector,AX
- POP AX
- RET
- init_flp ENDP
-
- ; ------------ Devolver tamaño de la pista (para la unidad AL)
- ; en AX (pistas 1ª parte) y BX (2ª parte) así como los
- ; límites máximos en CX (1ª parte) y DX (2ª parte) y
- ; las velocidades de transferencia en DI.
-
- get_tpista PROC
- MOV DL,AL
- MOV AH,8
- CALL tipo_disco ; tipo de la unidad
- LEA AX,pista_525
- CMP BL,2
- JE infpis_ok ; 1.2M
- LEA AX,pista_35
- CMP BL,4 ; 1.44M
- JE infpis_ok
- CMP param_ed,ON
- JNE infpis_ok
- LEA AX,pista_ed ; 2.88M
- infpis_ok: MOV BX,10 ; offset información DD
- CMP param_dd,ON
- JE infdis_ok
- MOV BX,20 ; offset información DH
- CMP param_dh,ON
- JE infdis_ok
- XOR BX,BX ; offset información HD
- infdis_ok: ADD BX,AX ; direccionar tabla datos
- MOV AX,tpista
- CMP param_b,ON
- JE tp1_ok ; indicado con /B
- MOV AX,[BX]
- tp1_ok: MOV CX,[BX+2]
- MOV DX,[BX+6]
- MOV DI,[BX+8]
- MOV BX,[BX+4]
- CMP param_b,ON
- JNE tp2_ok
- CMP param_dh,ON
- JNE tp3_ok
-
- XPUSH <SI, DI, CX, DX> ; * caso 5¼ /DH
- MUL WORD PTR maxpistas
- MOV DI,DX
- MOV SI,AX
- MOV AX,t_525_hd ; tamaño * maxpistas * t_525_hd
- CALL mult32x16
- MOV AX,20
- CALL divi48x15 ; div 20 (problema de rango)
- XPUSH <DX, DI, SI>
- MOV AX,WORD PTR maxpistas
- SUB AL,frontera
- SBB AH,0
- MOV BX,t_525_dd
- MUL BX
- MOV CX,DX
- MOV BX,AX ; CX:BX = t_525_dd*(maxp - FRO)
- XOR DI,DI
- MOV SI,t_525_hd
- MOV AL,frontera
- MOV AH,0
- CALL mult32x16
- ADD SI,BX
- ADC DI,CX
- ADC DX,0 ; denominador
- MOV AX,20
- SUB SI,24 ; redondeo
- SBB DI,0
- SBB DX,0
- CALL divi48x15 ; div 20 (problema de rango)
- MOV AX,SI ; cabe en 15 bits
- XPOP <SI, DI, DX>
- CALL divi48x15
- INC SI ; redondeo por el resto
- MOV AX,SI ; tamaño primera parte disco
- PUSH AX ; **
- MOV BX,t_525_dd
- MUL BX
- MOV BX,t_525_hd
- DIV BX
- MOV BX,AX ; tamaño segunda parte disco
- POP AX ; **
- XPOP <DX, CX, DI, SI> ; *
- JMP tp2_ok
-
- tp3_ok: MOV BX,AX ; /B afecta a todo el disco
- tp2_ok: RET
- get_tpista ENDP
-
- ; ------------ Imprimir nº de 8 bits en AL.
-
- print_8 PROC
- XPUSH <AX, CX, DX>
- MOV AH,0
- XOR DX,DX
- MOV CL,2
- CALL print_32
- XPOP <DX, CX AX>
- RET
- print_8 ENDP
-
- ; --- Imprimir un nº decimal de 32 bits en DXAX formateado por CL.
- ;
- ; Entradas:
- ; Si bit 4 = 1 --> se imprimirán signos separadores de millar
- ; bits 0-3 = nº total de dígitos (incluyendo separadores de
- ; millar y parte fraccional)
- ; bits 5-7 = nº de dígitos de la parte fraccional (cuantos
- ; dígitos de DXAX, empezando por la derecha,
- ; se consideran parte fraccional, e irán precedidos
- ; del correspondiente separador)
- ;
- ; Salidas: nº impreso, ningún registro modificado.
- ;
- ; * Ejemplo, si DXAX=9384320 y CL=010 1 1011
- ; se imprimirá ( '_' representa un espacio en blanco ): __93.843,20
-
- print_32 PROC
- PUSH DS
- PUSH ES
- PUSH CS
- PUSH CS
- POP DS
- POP ES
- PUSH AX ; preservar todos los registros
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- PUSHF
- MOV formato_pr32,CL ; byte del formato de impresión elegido
- MOV CX,",."
- CMP idioma_sp,ON
- JE separ_pr32
- XCHG CH,CL
- separ_pr32: MOV millares_pr32,CL ; separador de millares
- MOV fracc_pr32,CH ; separador parte fraccional
- MOV BX,OFFSET tabla_pr32
- MOV CX,10
- digit_pr32: PUSH CX
- PUSH AX
- PUSH DX
- XOR DI,DI
- MOV SI,1 ; DISI = 1
- DEC CX ; CX - 1
- JCXZ hecho_pr32
- factor_pr32: SAL SI,1
- RCL DI,1 ; DISI * 2
- MOV DX,DI
- MOV AX,SI
- SAL SI,1
- RCL DI,1
- SAL SI,1
- RCL DI,1 ; DISI * 8
- ADD SI,AX
- ADC DI,DX ; DISI = DISI*8 + DISI*2 = DISI*10
- LOOP factor_pr32 ; DISI = DISI*10*10* ... (CX-1 veces)
- hecho_pr32: POP DX ; luego DISI = 10 elevado a (CX-1)
- POP AX ; CX se recuperará más tarde
- MOV CL,0FFh
- rep_sub_pr32: INC CL
- SUB AX,SI
- SBB DX,DI ; DXAX = DXAX - DISI
- JNC rep_sub_pr32 ; restar el factor cuanto se pueda
- ADD AX,SI ; subsanar el desbordamiento:
- ADC DX,DI ; DXAX = DXAX + DISI
- ADD CL,'0' ; pasar binario a ASCII
- MOV [BX],CL
- POP CX ; CX se recupera ahora
- INC BX
- LOOP digit_pr32 ; próximo dígito del número
- STD ; transferencias (MOVS) hacia atrás
- DEC BX ; BX apunta al último dígito
- MOV final_pr32,BX ; último dígito
- MOV ent_frac_pr32,BX ; frontera parte entera/fraccional
- MOV CL,5
- MOV AL,formato_pr32
- SHR AL,CL ; AL = nº de decimales
- AND AL,AL
- JZ no_frac_pr32 ; ninguno
- MOV CL,AL
- XOR CH,CH
- MOV SI,final_pr32
- MOV DI,SI
- INC DI
- REP MOVSB ; correr cadena arriba (hacer hueco)
- INC final_pr32
- MOV AL,fracc_pr32
- MOV [DI],AL ; poner separador de parte fraccional
- MOV ent_frac_pr32,SI ; indicar nueva frontera
- no_frac_pr32: MOV AL,formato_pr32
- TEST AL,16 ; interpretar el formato especificado
- JZ poner_pr32 ; imprimir como tal
- entera_pr32: MOV CX,final_pr32 ; añadir separadores de millar
- SUB CX,ent_frac_pr32
- ADD CX,3
- MOV SI,final_pr32
- MOV DI,SI
- INC DI
- REP MOVSB ; correr cadena arriba (hacer hueco)
- MOV AL,millares_pr32
- MOV [DI],AL ; poner separador de millares
- INC final_pr32
- MOV ent_frac_pr32,SI ; usar esta variable como puntero
- SUB SI,OFFSET tabla_pr32
- CMP SI,3
- JAE entera_pr32 ; próximo separador
- poner_pr32: MOV BX,final_pr32
- MOV BYTE PTR [BX+1],0 ; delimitador de fin de cadena
- MOV BX,OFFSET tabla_pr32
- MOV principio_pr32,BX ; inicio de cadena
- limpiar_pr32: MOV AL,[BX]
- CMP AL,'0'
- JE blanco_pr32 ; cero a la izda --> poner " "
- CMP AL,millares_pr32 ; separador millares a la izda
- JE blanco_pr32
- CMP AL,fracc_pr32
- JNE acabar_pr32
- MOV BYTE PTR [BX-1],'0' ; reponer 0 antes de la coma
- DEC principio_pr32
- acabar_pr32: MOV AL,formato_pr32 ; imprimir
- AND AL,00001111b
- XOR AH,AH
- MOV DX,final_pr32
- SUB DX,AX
- INC DX ; DX = offset 'principio'
- AND AX,AX
- JNZ format_pr32 ; longitud especificada por el usuario
- MOV DX,principio_pr32 ; longitud obtenida del número
- format_pr32: CALL print
- POPF ; restaurar todos los registros
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
- POP AX
- POP ES
- POP DS
- RET ; salida del procedimiento
- blanco_pr32: MOV BYTE PTR [BX],' ' ; sustituir 0 ó separador de millares
- INC BX ; a la izda. por espacio en blanco
- INC principio_pr32
- CMP BX,final_pr32
- JB limpiar_pr32
- MOV DX,BX ; es el número 0.000.000.00X
- JMP SHORT acabar_pr32 ; imprimir
- formato_pr32 DB 0
- DB 5 DUP (' ') ; espacios en blanco para cubrir la
- ; mayor plantilla que pueda ser espe-
- ; cificada en el formato
- tabla_pr32 DT 0 ; reservar 14 bytes (nº más ., más ASCIIZ)
- DW 0,0 ; aquí se solapa un buffer de 32 bytes
- millares_pr32 DB '.' ; separador de millares
- fracc_pr32 DB ',' ; " parte fraccional
- final_pr32 DW 0 ; offset al último byte a imprimir
- principio_pr32 DW 0 ; " " primer " " "
- ent_frac_pr32 DW 0 ; offset a la frontera entero-fracc.
- DT 0 ; $ - tabla_pr32 = 32 bytes usados por
- ; INT 21h al principio de print_32
- print_32 ENDP
-
- ; ------------ Crear tabla con información para formatear.
-
- genera_infof PROC
- XPUSHA
- PUSH ES
- MOV ES,sbuffer
- MOV AL,[SI].infb.mfrontera
- CMP [SI].cilindro,AL ; 1ª/2ª mitad del disco
- MOV AX,tpistamax1
- JB pl_ok
- MOV AX,tpistamax2
- pl_ok: SUB AX,146 ; respetar inicio pista
- XOR DX,DX
- MOV CX,256+62+PRE_GAP3
- DIV CX ; AX sectores de 256 bytes caben
- MOV CX,AX
- MOV BX,360 ; grados de la circunferencia
- MOV AX,sliding_x
- MUL CX
- DIV BX ; AL = sliding X en sectores
- PUSH AX ; *
- MOV AX,sliding_y
- MUL CX
- DIV BX ; AL = sliding Y en sectores
- POP BX ; *
- MOV AH,AL ; sliding Y
- MOV AL,BL ; sliding X
- PUSH AX ; *
- ADD AL,AH
- MOV AH,[SI].cilindro
- INC AH ; desplazar incluso cilindro 0
- MUL AH ; (cilindro+1) * (X+Y)
- MOV DX,AX
- POP AX ; *
- MUL [SI].cabezal ; cabezal * X
- ADD AX,DX
- XOR DX,DX ; DX:AX = cil * (X+Y) + cab * X
- DIV CX ; DL = DX:AX MOD sectores = dis
- SUB DL,CL
- NEG DL ; DL = sectores - dis
- INC DL ; primer_sector
- CMP DL,CL
- JB gen_ps_ok
- MOV DL,0
- gen_ps_ok: MOV BL,CL ; nº sectores
- MOV AL,[SI].cabezal
- MOV AH,1
- XOR DI,DI
- MOV ES:[DI],CL ; sectores
- MOV ES:[DI+1],AH ; de tamaño 1 (256 bytes)
- MOV DH,[SI].cilindro
- ADD DI,2
- gen_info: MOV ES:[DI],DH ; cilindro
- MOV ES:[DI+1],AL ; cabezal
- MOV ES:[DI+2],DL ; sector
- MOV ES:[DI+3],AH ; tamaño 1 (256 bytes)
- AND DL,DL
- JNZ gen_tam_ok
- MOV AH,[SI].tsector
- MOV ES:[DI+3],AH ; el sector 0 es especial
- MOV AH,1
- gen_tam_ok: INC DL
- CMP DL,BL
- JB gen_sec_ok
- MOV DL,0 ; comenzar desde sector 0
- gen_sec_ok: ADD DI,4
- LOOP gen_info
- POP ES
- XPOPA
- RET
- genera_infof ENDP
-
- ; ------------ Formatear una pista.
-
- formatea_pista PROC
- XPUSHA ; *
- PUSH ES ; **
- MOV ES,sbuffer
- MOV CL,ES:[0]
- MOV CH,0 ; CX sectores
- SHL CX,1
- SHL CX,1
- DEC CX ; nº de bytes - 1
- MOV AX,ES
- MOV DI,2
- CALL calc_dir_DMA ; AX:DI -> base BX y página AH
- MOV AL,F_WRITE ; modo DMA para escribir
- CALL _prepara_DMA ; programar realmente el DMA
- MOV AL,F_FORMAT
- CALL fdc_write
- JC fallo_fmt
- MOV AL,[SI].cabezal
- SHL AL,1
- SHL AL,1
- OR AL,[SI].unidad
- CALL fdc_write ; byte 1 de la orden
- JC fallo_fmt
- MOV AL,ES:[1]
- CALL fdc_write ; tamaño general
- JC fallo_fmt
- MOV AL,ES:[0]
- CALL fdc_write ; nº sectores
- MOV AL,PRE_GAP3
- CALL fdc_write ; GAP3
- MOV AL,4Eh
- CALL reset_irq
- CALL fdc_write ; byte de relleno 4Eh (GAP)
- CALL espera_int
- fallo_fmt: PUSHF
- LEA BX,fdc_result
- MOV CX,7
- format_res: CALL fdc_read ; leyendo resultados
- MOV [BX],AL
- INC BX
- LOOP format_res
- POPF
- JC fallo_format
- TEST fdc_result,11000000b
- JZ format_ret
- fallo_format: STC ; fallo
- CALL set_err
- format_ret: POP ES ; **
- XPOPA ; *
- RET
- formatea_pista ENDP
-
- ; ------------ Devolver nº aleatorio de 16 bits en AX.
-
- rnd PROC
- CMP semilla,0
- JNE dev_rnd
- PUSH DS
- MOV AX,40h
- MOV DS,AX
- MOV AX,DS:[6Ch] ; contador hora BIOS
- POP DS ; como semilla
- MOV semilla,AX
- dev_rnd: XPUSH <BX, CX>
- MOV AX,semilla
- MOV BX,AX
- MOV CL,7
- SHR AX,CL
- XOR AX,BX
- AND AX,1
- ROR AX,1
- SHR BX,1
- OR AX,BX
- MOV semilla,AX
- XPOP <CX, BX>
- RET
- semilla DW 0
- rnd ENDP
-
-
- ; ***********************************************
- ; * *
- ; * D A T O S N O R E S I D E N T E S *
- ; * *
- ; ***********************************************
-
- ; ------------ Parámetros soportados
-
- param_ayuda DB OFF ; a ON si se indicó /? /H ó ?
- param_dd DB OFF ; a ON si se indicó /DD
- param_dh DB OFF ; a ON si se indicó /DH
- param_ed DB OFF ; a ON si se indicó /ED
- param_dron DB OFF ; a ON si se indicó /DRON
- param_droff DB OFF ; a ON si se indicó /DROFF
- param_dwon DB OFF ; a ON si se indicó /DWON
- param_dwoff DB OFF ; a ON si se indicó /DWOFF
- param_n DB OFF ; a ON si se indicó /N
- param_k DB OFF ; a ON si se indicó /K
- param_test DB OFF ; a ON si se indicó /TEST
- param_nodma DB OFF ; a ON si se indicó /NODMA
- param_ems DB OFF ; a ON si se indicó /EMS
- param_q DB OFF ; a ON si se indicó /Q
- param_t DB OFF ; a ON si se indicó /T=
- param_r DB OFF ; a ON si se indicó /R=
- param_c DB OFF ; a ON si se indicó /C=
- param_s DB OFF ; a ON si se indicó /S=
- param_f DB OFF ; a ON si se indicó /F=
- param_b DB OFF ; a ON si se indicó /B=
- param_x DB OFF ; a ON si se indicó /X=
- param_y DB OFF ; a ON si se indicó /Y=
- param_m DB OFF ; a ON si se indicó /M=
- param_g DB OFF ; a ON si se indicó /G=
- ptr_label DW 0 ; != NULL si se indicó /L
- ptr_ilabel DW 0 ; != NULL si se indicó /V
- disquetera DB -1 ; unidad seleccionada si se indica
-
- parametros LABEL BYTE
- DB "*:",3
- DB 'A'
- DB 26
- DW disquetera
-
- DB "?",0
- DW param_ayuda
- DB ON
-
- DB "/?",0
- DW param_ayuda
- DB ON
-
- DB "/H",0
- DW param_ayuda
- DB ON
-
- DB "/DD",0
- DW param_dd
- DB ON
-
- DB "/DH",0
- DW param_dh
- DB ON
-
- DB "/ED",0
- DW param_ed
- DB ON
-
- DB "/DRON",0
- DW param_dron
- DB ON
-
- DB "/DROFf",0
- DW param_droff
- DB ON
-
- DB "/DWON",0
- DW param_dwon
- DB ON
-
- DB "/DWOFf",0
- DW param_dwoff
- DB ON
-
- DB "/TEst",0
- DW param_test
- DB ON
-
- DB "/NOdma",0
- DW param_nodma
- DB ON
-
- DB "/EMs",0
- DW param_ems
- DB ON
-
- DB "/B",1
- DW 0, MPISTA
- DW tpista
- DW param_b
- DB ON
-
- DB "/X",1
- DW 0, 359
- DW sliding_x
- DW param_x
- DB ON
-
- DB "/Y",1
- DW 0, 359
- DW sliding_y
- DW param_y
- DB ON
-
- DB "/M",1
- DW 0, 86
- DW frontera
- DW param_m
- DB ON
-
- DB "/G",1
- DW 0, 999
- DW gaprw
- DW param_g
- DB ON
-
- DB "/N",0
- DW param_n
- DB ON
-
- DB "/K",0
- DW param_k
- DB ON
-
- DB "/I",0
- DW param_i
- DB ON
-
- DB "/Q",0
- DW param_q
- DB ON
-
- DB "/T",1
- DW 80, 86
- DW maxpistas
- DW param_t
- DB ON
-
- DB "/C",2
- DW 8,128,256,512,1024,2048,4096,8192,16384
- DW tcluster
- DW param_c
- DB ON
-
- DB "/S",2
- DW 3,128,256,512
- DW bsectini
- DW param_s
- DB ON
-
- DB "/R",1
- DW 1, 240
- DW rootdir
- DW param_r
- DB ON
-
- DB "/F",1
- DW 1, 2
- DW nfats
- DW param_f
- DB ON
-
- DB "/L",4
- DW ptr_label
-
- DB "/V",4
- DW ptr_ilabel
-
- DB 0 ; fin de la tabla
-
- ; ------------ Constantes y variables
-
- ON EQU 1 ; constantes booleanas
- OFF EQU 0
-
- ERRSINTAX EQU 1 ; tipos de errores
- MALDOS EQU 2
- MALDRV EQU 4
- MALBIOS EQU 8
- ERRRANGO EQU 16
- POCAMEM EQU 32
- YAINST EQU 64
- NOINST EQU 128
- MX64FULL EQU 256
- DMACRUCE EQU 512
- DMAPOCO EQU 1024
- PARAMCONFIG EQU 2048
-
- ABORTADO EQU 8
- NOPREP EQU 16
- MALADENS EQU 32
- PROTESCR EQU 64
- MALSYS EQU 128
- MUCHAFAT EQU 256
- MUCHAPISTA EQU 512
-
- error DW 0 ; de instalación
- errw DW 0 ; al formatear/test, etc.
- disco DB ?
- emmtipo DW ? ; tipo de EMM en INT 4Bh
- psp DW ? ; dirección del PSP
-
- emm_id DB "EMMXXXX0" ; identificación controlador EMS
-
- emm_nombre DB "2MGUI",0,0,0 ; nombre para el handle EMS
-
- null DB "NUL",0 ; dispositivo NUL
-
- instalado DB ? ; a ON si 2MGUI instalado
-
- offsets_ints DW 3 ; número de vectores interceptados
- DB 8h ; tabla de offsets de los vectores
- DW ges_int08 ; de interrupción interceptados
- DB 13h
- DW ges_int13
- DB 2Fh
- DW ges_int2F
-
- ; --- El disco está dividido en dos partes: desde el
- ; cilindro 0 hasta FRONTERA-1 y desde FRONTERA
- ; hasta maxpistas-1. Cada parte tiene sus propias
- ; características (en la práctica, sólo en 360DH).
-
- pista_525 LABEL WORD
- DW t_525_hd ; 1.2M 1ª parte HD
- DW m_525_hd ; límite físico 1ª parte HD
- DW t_525_hd ; 1.2M 2ª parte HD
- DW m_525_hd ; límite físico 2ª parte HD
- DW 0000h ; velocidad
- DW t_525_dd ; 1.2M 1ª parte DD
- DW m_525_dd ; límite físico 1ª parte DD
- DW t_525_dd ; 1.2M 2ª parte DD
- DW m_525_dd ; límite físico 2ª parte DD
- DW 0101h ; velocidad
- DW t_525_hd ; 1.2M 1ª parte DH
- DW m_525_hd ; límite físico 1ª parte DH
- DW t_525_dd ; 1.2M 2ª parte DH
- DW m_525_dd ; límite físico 2ª parte DH
- DW 0100h ; velocidad
- pista_35 LABEL WORD
- DW t_35_hd ; 1.44M 1ª parte HD
- DW m_35_hd ; límite físico 1ª parte HD
- DW t_35_hd ; 1.44M 2ª parte HD
- DW m_35_hd ; límite físico 2ª parte HD
- DW 0000h ; velocidad
- DW t_35_dd ; 1.44M 1ª parte DD
- DW m_35_dd ; límite físico 1ª parte DD
- DW t_35_dd ; 1.44M 2ª parte DD
- DW m_35_dd ; límite físico 2ª parte DD
- DW 0101h ; velocidad
- DW t_35_dd ; 1.44M 1ª parte DD
- DW m_35_dd ; límite físico 1ª parte DD
- DW t_35_dd ; 1.44M 2ª parte DD
- DW m_35_dd ; límite físico 2ª parte DD
- DW 0101h ; velocidad
- pista_ed LABEL WORD
- DW t_35_ed ; 2.88M 1ª parte ED
- DW m_35_ed ; límite físico 1ª parte ED
- DW t_35_ed ; 2.88M 2ª parte ED
- DW m_35_ed ; límite físico 2ª parte ED
- DW 0303h ; velocidad
- DW t_35_ed ; 2.88M 1ª parte ED
- DW m_35_ed ; límite físico 1ª parte ED
- DW t_35_ed ; 2.88M 2ª parte ED
- DW m_35_ed ; límite físico 2ª parte ED
- DW 0303h ; velocidad
- DW t_35_ed ; 2.88M 1ª parte ED
- DW m_35_ed ; límite físico 1ª parte ED
- DW t_35_ed ; 2.88M 2ª parte ED
- DW m_35_ed ; límite físico 2ª parte ED
- DW 0303h ; velocidad
-
- maxpistas DB PISTAS
- DB 0 ; ¡la captura de parámetros usa DW, no DB!
- rootdir DW MINROOT ; mínimo por defecto
- bsectini DW SECTDEF ; tamaño de sector por defecto
- tcluster DW CLUSDEF ; tamaño de clúster por defecto
- nfats DB 1
- DB 0 ; ¡la captura de parámetros usa DW, no DB!
- tipofat DB ?
- fbuffer DW 0 ; segmento para la FAT
- srootdir DW ? ; sectores ocupados por el raíz
-
- tpista DW ? ; valor de /B= si se indica
- tpistamax1 DW ? ; bytes por pista físicamente máximos
- tpistamax2 DW ? ; ...y en la segunda parte del disco
- sliding_x DW SLID_X ; grados angulares de sliding /X
- sliding_y DW SLID_Y ; grados angulares de sliding /Y
- frontera DB FRONT ; frontera división del disco 2 mitades
- DB 0 ; ¡la captura de parámetros usa DW, no DB!
-
- tmodo DB ? ; 0->pista a 0, 1->con datos aleatorios
- bytes_ok DW ? ; bytes bien leídos durante el test
- bytes_max DW ? ; máximos bytes soportados último éxito
- tmax DW ? ; máximo/mínima capacidad por pista
- tmin DW ? ; durante el test
- iter DW ? ; contador de iteraciones
- irq6 DB ? ; a ON cuando llega dicha IRQ en el test
- cnt_h DW ? ; contadores de tiempo para spin
- cnt_l DW ?
- dif_l DW 0 ; variación de los contadores
- dif_h DW 0
- cntms_h DW 0 ; milisegundos * 1000
- cntms_l DW 0
- dif0_l DW 0 ; valor inicial
- dif0_h DW 0
-
- sector_boot LABEL BYTE ; sector de arranque de 128 bytes
- JMP SHORT arranque
- NOP
- DB "2MGUI-10" ; ID sistema: versión 1.0
- boot_tsect DW ? ; bytes/sector
- bscluster DB ? ; sectores por cluster
- DW 1 ; sectores reservados al principio
- bnfats DB ? ; nº copias de la FAT
- brootdir DW ? ; entradas al directorio raíz
- bsectores DW ? ; nº total de sectores del disco
- media_id DB 0FAh ; byte descriptor de medio
- bsectfat DW ? ; sectores ocupados por la FAT
- DW 1 ; sectores por pista
- DW 1 ; nº de cabezales
- DD 0 ; sectores especiales reservados
- DD 0 ; nº sectores (unidad 32 bit)
- DB 0 ; unidad física
- DB 0 ; reservado
- DB 29h ; disco con número de serie
- bserie DD 12345678h ; número de serie
- DB "NO NAME " ; título del disco
- ftipo DB "FAT12 " ; tipo de FAT
- arranque: CLI
- HLT
- DB "(C) 1995 "
- DB "Ciriaco García de Celis - "
- DB "Valladolid/Spain"
- DB 0
- PINFOBOOT EQU 74h ; offset físico del área con información
- bootp InfoBoot <> ; información del BOOT
- DB 126 DUP (0)
- DW 0AA55h ; para el DOS, por si es de 256 bytes
- DB 254 DUP (0)
- DW 0AA55h ; para el DOS, por si es de 512 bytes
-
- ; --- Información IOCTL por defecto.
-
- info_drv120 DB 4, 1 ; sectores iguales / tipo 1.2M
- DW 2, 13118 ; detecta cambio / nº pistas
- DB 0 ; tipo de soporte
- DW 128 ; BPB: bytes por sector
- DB 8 ; BPB: sectores por cluster
- DW 1 ; BPB: sectores reservados
- DB 1 ; BPB: número de FATs
- DW 132 ; BPB: entradas en el raíz
- DW 13118 ; BPB: nº total de sectores
- DB 0FAh ; BPB: descriptor de medio
- DW 20 ; BPB: sectores por FAT
- DW 1, 1 ; BPB: sectores pista / cabezas
- DB 14 DUP (0) ; BPB: restantes campos
-
- info_drv144 DB 4, 7 ; sectores iguales / tipo 1.44M
- DW 2, 15776 ; detecta cambio / nº pistas
- DB 0 ; tipo de soporte
- DW 128 ; BPB: bytes por sector
- DB 8 ; BPB: sectores por cluster
- DW 1 ; BPB: sectores reservados
- DB 1 ; BPB: número de FATs
- DW 156 ; BPB: entradas en el raíz
- DW 15776 ; BPB: nº total de sectores
- DB 0FAh ; BPB: descriptor de medio
- DW 24 ; BPB: sectores por FAT
- DW 1, 1 ; BPB: sectores pista / cabezas
- DB 14 DUP (0) ; BPB: restantes campos
-
- info_drv288 DB 4, 9 ; sectores iguales / tipo 2.88M
- DW 2, 31552 ; detecta cambio / nº pistas
- DB 0 ; tipo de soporte
- DW 128 ; BPB: bytes por sector
- DB 16 ; BPB: sectores por cluster
- DW 1 ; BPB: sectores reservados
- DB 1 ; BPB: número de FATs
- DW 156 ; BPB: entradas en el raíz
- DW 31552 ; BPB: nº total de sectores
- DB 0FAh ; BPB: descriptor de medio
- DW 24 ; BPB: sectores por FAT
- DW 1, 1 ; BPB: sectores pista / cabezas
- DB 14 DUP (0) ; BPB: restantes campos
-
- ; ------------ Mensajes de instalación.
-
- programa_txt DB 13,10,"2MGUI 1.0 ",13,10,0
-
- instalado_txt DB " Instalado en unidad(es) "
- tabla_letras1 DB "A: ",13,10,255
- DB " Installed on drive(s) "
- tabla_letras2 DB "A: ",13,10,0
-
- errxtdma_txt DB " - Nota: Sistema PC/XT, soportado sólo modo DMA.",13,10,255
- DB " - Note: PC/XT system, supported only DMA mode.",13,10,0
-
- erremsins_txt DB " - Nota: No ha sido posible utilizar memoria EMS.",13,10,255
- DB " - Note: It isn't possible to use EMS memory.",13,10,0
-
- erremsdma_txt DB " - Nota: Sólo se puede utilizar EMS en modo /NODMA.",13,10,255
- DB " - Note: To use EMS is only possible in /NODMA mode.",13,10,0
-
- mal_dos_txt DB " - Error: Necesario DOS 3.30 o posterior.",13,10,255
- DB " - Error: Needs DOS 3.30 or above.",13,10,0
-
- mal_bios_txt DB " - Error: No puedo detectar el tipo de las unidades. Instale 2M-?BIOS antes.",13,10,255
- DB " - Error: Impossible to detect drive types. Please install 2M-?BIOS before.",13,10,0
-
- mal_drv_txt DB " - Error: Necesaria(s) unidad(es) de alta densidad.",13,10,255
- DB " - Error: Needs high-density floppy drive(s).",13,10,0
-
- ya_ins_txt DB " - Error: Programa ya instalado en memoria.",13,10,255
- DB " - Error: Program already loaded on memory.",13,10,0
-
- dma_front_txt DB " - Consejo: Modifique la ubicación en memoria de este programa (variando el",13,10
- DB " orden de instalación de dispositivos) o, alternativamente, pruebe",13,10
- DB " a instalarlo en modo NO-DMA. El motivo es economizar memoria, ya",13,10
- DB " que se cruza una frontera de DMA. No obstante, el programa puede",13,10
- DB " funcionar perfectamente así, ocupando más memoria.",13,10,255
- DB " - Advice: Modify the memory location of this utility (variying the devices",13,10
- DB " installation order) or install the program in Non-DMA mode, to save",13,10
- DB " memory. The problem is that 2MGUI crosses a DMA frontier. But this",13,10
- DB " program can work correctly in this way (taking more memory).",13,10,0
-
- dma_poco_txt DB " - Nota: El buffer DMA de su controlador de memoria es demasiado pequeño,",13,10
- DB " auméntelo a 13 (1.44M) ó 25 (2.88M) Kbytes.",255
- DB " - Note: The DMA buffer of your memory manager is too small; set it",13,10
- DB " to 13 (1.44M) or 25 (2.88M) Kbytes.",0
-
- emm_qemm_txt DB " En su controlador de",13,10
- DB " memoria (QEMM) basta que le añada la opción DMA=13 ó DMA=25.",13,10,255
- DB " With your memory manager (QEMM) you must add",13,10
- DB " to it a DMA=13 or DMA=25 switch.",13,10,0
-
- nocabe_txt DB " Instalación imposible:",13,10
- DB " Ya hay 64 programas residentes con la misma técnica.",13,10,255
- DB " Unable to install:",13,10
- DB " There are already 64 TSR's with the same technique.",13,10,0
-
- err_sintax_txt DB " - Error de sintaxis o parámetro fuera de rango.",13,10,255
- DB " - Syntax error or parameter out of range.",13,10,0
- pet_ayuda_txt DB " Ejecute 2MGUI /? si desea obtener ayuda.",13,10,255
- DB " Execute 2MGUI /? to obtain more help.",13,10,0
-
- no_ins_txt DB " - Error: Instale este programa primero en CONFIG.SYS",13,10,255
- DB " - Error: First, install this program in CONFIG.SYS",13,10,0
-
- err_mem_txt DB " - Error: memoria insuficiente.",13,10,255
- DB " - Error: insufficient memory.",13,10,0
-
- ; ------------ Mensajes varios.
-
- limpia_txt DB 13," ",13,0
-
- lin_txt DB "───────────────────────────────────────────────────────────────────────────────",13,10,0
-
- err_prot_txt DB 13," - Disco protegido contra escritura.",13,10,255
- DB 13," - Write protected disk error.",13,10,0
-
- no_prep_txt DB 13," - Unidad no preparada.",13,10,255
- DB 13," - Drive not ready.",13,10,0
-
- mal_dens_txt DB 13," - Anomalía general. ¿Densidad incorrecta?.",13,10,255
- DB 13," - General failure. Incorrect density?.",13,10,0
-
- mal_unidad_txt DB " - La unidad no existe o no es de alta densidad.",13,10,255
- DB " - Diskette drive doesn't exist or it isn't high-density.",13,10,0
-
- dh_test_txt DB " - El parámetro /DH no puede indicarse junto a /TEST.",13,10,255
- DB " - The /DH switch can not be used with /TEST.",13,10,0
-
- pconfig_txt DB " - El parámetro /NODMA sólo puede indicarse en CONFIG.SYS o con /TEST; y ",13,10
- DB " el parámetro /EMS sólo puede indicarse en CONFIG.SYS y junto a /NODMA.",13,10,255
- DB " - The /NODMA switch can only be used in CONFIG.SYS or with /TEST; and",13,10
- DB " the /EMS switch can only be used in CONFIG.SYS and with /NODMA.",13,10,0
-
- crlf_txt DB 13,10,0
-
- ; ------------ Informe de unidades.
-
- hay_2mgui_txt DB 13,10
- DB "2MGUI 1.0 ya instalado en memoria.",13,10,255
- DB 13,10
- DB "2MGUI 1.0 already installed in memory.",13,10,0
- hay_en_txt DB " - Nueva unidad ",255
- DB " - New drive ",0
- nueva_u DB "E: ",0
- hay2_txt DB " (unidad física ",255
- DB " (physical drive ",0
- vieja_u DB "A"
- DB ":)",13,10,0
- gap_txt DB " - GAP anti-FIFO de",255
- DB " - Anti-FIFO GAP of",0
- dma1_txt DB " bytes y modo ",255
- DB " bytes and ",0
- dmano_txt DB "NO-",255,"non-",0
- dma2_txt DB "DMA.",13,10,255
- DB "DMA mode.",13,10,0
-
- buffer_ems_txt DB " - Buffer interno ubicado en memoria EMS.",13,10,255
- DB " - Internal buffer placed in EMS memory.",13,10,0
-
- cache_off_txt DB " - Escritura retardada desactivada.",13,10,255
- DB " - Delayed-write disabled.",13,10,0
-
- sopdr_on_txt DB " - Soporte para DISKCOPY DR-DOS y Novell DOS activo.",13,10,255
- DB " - DR-DOS and Novell DOS DISKCOPY support enabled.",13,10,0
-
- ; ------------ Mensajes de formateo.
-
- no_2mgui_txt DB 13,10,"2MGUI 1.0",13,10
- DB " - Error: La unidad indicada no es un dispositivo 2MGUI.",13,10,255
- DB 13,10,"2MGUI 1.0",13,10
- DB " - Error: Drive indicated does not is a 2MGUI device.",13,10,0
-
- mucha_fat_txt DB 13,10,"2MGUI 1.0",13,10
- DB " - Error: Memoria insuficiente para una FAT tan grande.",13,10,255
- DB 13,10,"2MGUI 1.0",13,10
- DB " - Error: Insufficient memory for so big a FAT.",13,10,0
-
- fmtm1_txt DB 13,10,"2MGUI 1.0 Formateando",255
- DB 13,10,"2MGUI 1.0 Formatting",0
- fmtm2_txt DB " bytes por pista en ",255
- DB " bytes per track in ",0
- fmtm3_txt DB ": ",0
- fmtm4_txt DB " (ESC Salir)",13,10,255
- DB " (ESC Aborts)",13,10,0
- fmtm5_txt DB " Inicializando disquete de ",255," Initializing ",0
- fmtm6_txt DB " con",255," diskette with",0
- fmtm7_txt DB "K",13,10,0
-
- pausaf_txt DB " Pulsa INTRO para formatear u otra tecla para terminar...",255
- DB " Press ENTER key to begin format or another key to exit...",0
-
- abortado_txt DB 13," - Formateo interrumpido por el usuario.",13,10,255
- DB 13," - Format aborted by user. ",13,10,0
-
- mucha_pis_txt DB 13," - La unidad no soporta tanta capacidad en la pista.",13,10,255
- DB 13," - This drive doesn't support so big a track.",13,10,0
-
- mal_sys_txt DB 13," - Fatal: fallo en áreas del sistema.",13,10,255
- DB 13," - Fatal: failure on system areas.",13,10,0
-
- cil_txt DB 13," Cilindro ",255,13," Cylinder ",0
- cab_txt DB " Cara",255," Side",0
- p_txt DB " ",0
- f_txt DB 8,8,8,8,8,"[F--]",0
- w_txt DB 8,8,8,8,8,"[-X-]",0
- v_txt DB 8,8,8,8,8,"[--V]",0
- error_txt DB 13,10,"Error",0
-
- t_drvs DW t360, t1200, t720, t1440, t2880, t2880
- t360 DB "360K",0
- t1200 DB "1.2M",0
- t720 DB "720K",0
- t1440 DB "1.44M",0
- t2880 DB "2.88M",0
-
- capacidad1_txt DB 13," Espacio bruto en disco de",255
- DB 13," Crude disk space is",0
- capacidad2_txt DB " bytes.",13,10,0
-
- etiq_txt DB " Etiqueta de volúmen ",255
- DB " Volume label ",0
-
- err_info_txt DB " - Retire e introduzca el disco antes de usarlo.",13,10,255
- DB " - Extract and reinsert the disk before using it.",13,10,0
-
- if1_txt DB " ficheros permitidos en el raíz.",13,10,255
- DB " file capacity of root directory.",13,10,0
- if2_txt DB " unidades de asignación.",13,10,255
- DB " total clusters on disk.",13,10,0
- if3_txt DB " bytes por unidad de asignación.",13,10,255
- DB " bytes per cluster.",13,10,0
- if4_txt DB " bytes totales en el disco.",13,10,255
- DB " total bytes on disk.",13,10,0
- if5_txt DB " bytes en sectores defectuosos.",13,10,255
- DB " bytes in bad tracks.",13,10,0
- if6_txt DB " bytes disponibles en el disco.",13,10,255
- DB " bytes available on disk.",13,10,0
-
- ; ------------ Mensajes para el test.
-
- test_txt1 DB 13,10,10,"2MGUI 1.0: TEST DE CAPACIDAD Y CALIDAD DE LA UNIDAD (ESC Salir)",13,10,255
- DB 13,10,10,"2MGUI 1.0: DISKETTE DRIVE MAXIMUM CAPACITY AND QUALITY TEST (ESC Aborts)",13,10,0
-
- test_txt_t DB " - Introduzca un disco que PERDERA TODOS LOS DATOS y pulse una tecla.",255
- DB " - Insert a disk which will LOSE ALL DATA and press any key.",0
-
- test_dma_txt DB " NOTA: El test puede producir resultados absurdos si su sistema o la",13,10
- DB " configuración del mismo no soporta el acceso en modo NO-DMA.",13,10,255
- DB " NOTE: This test may return nonsense results if your hardware or your",13,10
- DB " system configuration does not support Non-DMA diskette access mode.",13,10,0
-
- test_bdma_txt DB " NOTA: El buffer de DMA de su PC es demasiado pequeño; cambie la configuración",13,10
- DB " del controlador de memoria si se cuelga o si aparece alguna excepción. Con",13,10
- DB " QEMM basta añadir DMA=14 (1.44M) ó DMA=28 (2.88M) [algo más de lo normal].",13,10,255
- DB " NOTA: The maximum DMA buffer on your PC is too small; if the PC hangs during",13,10
- DB " the test or the EMM reports a exception, set a bigger buffer. With QEMM you",13,10
- DB " can add a DMA=14 (1.44M) or a DMA=28 (2.88M) [a little more than normal].",13,10,0
-
- test_txt2 DB 13," Probando ",255
- DB 13," Testing ",0
- test_txt3 DB " bytes en ",255
- DB " bytes in ",0
- test_txt4 DB ": [Disco de ",255
- DB ": [",0
- test_txt5 DB "] ",8,8,8,8,8,8,255
- DB " diskette] ",8,8,8,8,8,8,0
-
- test_r_txt11c DB 13," - Con ",255
- DB 13," - With ",0
- test_r_txt11s DB 13," - Sin ",255
- DB 13," - Without ",0
-
- test_r_txt12 DB "DMA y bits ",255
- DB "DMA and ",0
- test_r_txt12i DB "idénticos",255
- DB "identic bits",0
- test_r_txt12d DB "aleatorios",255
- DB "random bits",0
- test_r_txt13 DB " máxima capacidad por pista:",9,255
- DB " maximum size in each track:",9,0
- test_r_txt14 DB " bytes.",13,10,0
- test_r_txt15 DB " Mínimo posible GAP anti-FIFO detectado:",9,9,9,255
- DB " Possible minimum anti-FIFO GAP detected:",9,9,9,0
-
- aviso_gap_txt DB " AVISO:",13,10
- DB " - Su controladora precisa un GAP anti-FIFO mayor del establecido por defecto",13,10
- DB " por el programa; indíquelo explícitamente con la opción /G al instalarlo.",13,10,255
- DB " IMPORTANT:",13,10
- DB " - Your diskette controller needs a bigger anti-FIFO GAP than default settings",13,10
- DB " for program; set it with /G switch during program installation.",13,10,0
-
- test_res_txt3 DB " NOTAS SOBRE LOS PARAMETROS /B Y /G:",13,10
- DB " - El valor máximo soportado por /B para lograr más capacidad en los disquetes",13,10
- DB " será normalmente la capacidad máxima en la pista MENOS el GAP anti-FIFO (20",13,10
- DB " bytes por defecto). Es decir, reste 20 bytes de la capacidad de la pista",13,10
- DB " para obtener el valor máximo de /B. Ajustando también dicho GAP con /G se",13,10
- DB " puede obtener aún más capacidad. Cuidado: /G varía ligeramente con EMM386.",13,10
- DB " - Use siempre los datos del test de PEOR resultado de todos los realizados.",13,10
- DB " - Recuerde que estos disquetes serán *estropeados* al ser ESCRITOS por otras",13,10
- DB " unidades que admitan menos capacidad, aunque podrán LEERSE sin problemas.",13,10
- DB " - No utilice los valores límites si quiere que el programa funcione.",13,10,255
- DB " NOTES ABOUT /B AND /G SWITCHES:",13,10
- DB " - The maximum value supported by /B switch to get more disk capacity, will be",13,10
- DB " usually the maximum size per track but SUBSTRACTING anti-FIFO GAP (20 bytes",13,10
- DB " by default). This means that you have to substract 20 bytes to the maximum",13,10
- DB " track size to obtain /B value. Adjusting also this GAP with /G switch, it's",13,10
- DB " also possible to get more capacity. Warning: /G vary slightly with EMM386.",13,10
- DB " - You must use always the results of WORST test of all performed.",13,10
- DB " - Remember that this diskettes will be *damaged* when WRITTING them on other",13,10
- DB " drives with less capacity, although they can be READED without problems.",13,10
- DB " - Choosing minimum/maximum limits for values, the program may not work.",13,10,0
-
- disco_def_txt DB " - Nota: ¡Este disco quizá tenga defectuosa la pista 0!.",13,10,255
- DB " - Note: your diskette is perhaps damaged on track 0!",13,10,0
-
- test_res_mal DB " - Su unidad de disco es pésima y no admite siquiera la capacidad mínima",13,10
- DB " que necesita el programa. Cómprese otra mejor y, mientras tanto, no",13,10
- DB " escriba sobre los discos 2MGUI que le pasen otras personas.",13,10,255
- DB " - Your diskette drive is very bad and doesn't support the minimum size",13,10
- DB " needed by this program. You must buy a better drive and, meanwhile, do",13,10
- DB " not write on 2MGUI disks that other people send to you (only read!).",13,10,0 ;;;
-
- spin0_txt DB " TEST DE VELOCIDAD DE ROTACION:",13,10,255
- DB " ROTATION SPEED TEST:",13,10,0
-
- spin1_txt DB 13," - Período de rotación: ",255
- DB 13," - Rotation period: ",0
- spin2_txt DB " ms (",0
- spin3_txt DB ") [ESC-Fin]",255,") [ESC-End]",0
-
- spind_txt DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,"; con una desviación de ",255
- DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,"; with a shift of ",0
-
- spinf1_txt DB " ms",13,10," sobre al valor esperado de ",255
- DB " ms from the",13,10," expected value of ",0
- spinf2_txt DB " ms (unidad de ",255
- DB " ms (",0
- spinf3_txt DB " calidad).",13,10,255
- DB " quality drive).",13,10,0
-
- spinf_calidad DW 100
- DW c_altisima
- DW 250
- DW c_alta
- DW 500
- DW c_mediana
- DW 750
- DW c_mala
- DW 1000
- DW c_pesima
- DW 0
- DW c_pesima
- c_altisima DB "muy elevada",255,"very high",0
- c_alta DB "alta",255,"high",0
- c_mediana DB "mediana",255,"medium",0
- c_mala DB "baja",255,"bad",0
- c_pesima DB "pésima",255,"very bad",0
-
- spine_txt DB 13," Nota: ha habido algún problema calculando el período de rotación.",13,10,255
- DB 13," Note: it have been some problem computing rotation period.",13,10,0
-
- test_esc_txt DB 13," - TEST interrumpido por el usuario.",13,10,255
- DB 13," - TEST aborted by user.",13,10,0
-
- disco_mal_txt DB " RECUERDE QUE EL DISCO DE PRUEBA ESTA INSERVIBLE: DEBERA FORMATEARLO.",13,10,255
- DB " REMEMBER THAT TEST DISK IS NOW DAMAGED: YOU MUST FORMAT IT BEFORE USE.",13,10,0
-
- ; ------------ Ayuda.
-
- ayuda_txt LABEL BYTE
- DB 13,10,10
- DB " 2M GUINNESS 1.0 - ACCESO DIRECTO A DISCO SIN CONTROLADORA",13,10
- DB " (C) 1994-1995 Ciriaco García de Celis - Grupo Universitario de Informática",13,10
- DB " C/Renedo, 2, 4-C; 47005 Valladolid (España) - ciri@gui.uva.es - 2:341/21.8",13,10
- DB 10
- DB " 2MGUI [U:] [/DD] [/DH] [/ED] [/T:n] [/R:n] [/C:n] [/S:n] [/F:n] [/N] [/K]",13,10
- DB 10
- DB " Este programa obtiene *toda* la capacidad de los discos antes de formatear;",13,10
- DB " pudiendo incluso adaptarse a la velocidad de la unidad para obtener aún más.",13,10
- DB 10
- DB " Instálelo primero en el CONFIG.SYS con una línea como «DEVICE=2MGUI.EXE»;",13,10
- DB " a raíz de ello se crearán tantas nuevas letras como unidades de alta densidad",13,10
- DB " haya en el sistema. Los discos formateados por este programa sólo podrán ser",13,10
- DB " accedidos en esas nuevas unidades, que también soportan discos estándar (y 2M",13,10
- DB " si 2M está instalado). Es más, este programa permite utilizar discos 2M bajo",13,10
- DB " OS/2 en esas nuevas unidades. Al conmutar entre dichas unidades y las físicas",13,10
- DB " se simula un cambio de disco automático (y no se pide nuevo disco).",13,10
- DB 10
- DB " Para formatear los nuevos discos, ejecute 2MGUI indicando la unidad que les",13,10
- DB " soporta. Por defecto se utiliza alta densidad; /DD selecciona doble densidad,",13,10
- DB " /DH formatea 1/3 en alta densidad y 2/3 en doble (sólo discos de 360K) y /ED",13,10
- DB " selecciona 2.88M; /T indica el nº de pistas (80-86, por defecto 82), /R el",13,10
- DB " nº mínimo de ficheros en el raíz (1-240); /C el tamaño de cluster (128-16384)",13,10
- DB " y /S el de sector (128-512), ambos han de ser potencia de 2; /F el nº de FATs",13,10
- DB " (1-2); /N no verifica y /K evita las pausas.",13,10
- DB " (1/5) [PULSA UNA TECLA]",1
- DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8," ",13,10,10
- DB " ┌───────────┬───────────┬────────────┐",13,10
- DB " │ Doble │ Alta │ Extraalta │",13,10
- DB " ┌───────────────────────────────┼───────────┼───────────┼────────────┼──────┐",13,10
- DB " │ Récord absoluto previo a 2M │ 820.0 Kb │ 1394.0 Kb │ -- │ │",13,10
- DB " │ Capacidad máxima 2M (2MF /M) │ 902.0 Kb │ 1558.0 Kb │ -- │ 5.25 │",13,10
- DB " │ Capacidad mínima de 2MGUI │ 976.6 Kb │ 1639.8 Kb │ 1203.1 Kb# │ (5¼) │",13,10
- DB " │ Capacidad límite física (82p) │ 1001.0 Kb │ 1668.2 Kb │ 1228.8 Kb# │ │",13,10
- DB " ├───────────────────────────────┼───────────┼───────────┼────────────┼──────┤",13,10
- DB " │ Récord absoluto previo a 2M │ 984.0 Kb │ 1722.0 Kb │ 2880.0 Kb │ │",13,10
- DB " │ Capacidad máxima 2M (2MF /M) │ 1066.0 Kb │ 1886.0 Kb │ 3772.0 Kb* │ 3.5 │",13,10
- DB " │ Capacidad mínima de 2MGUI │ 1176.0 Kb │ 1972.0 Kb │ 3944.0 Kb* │ (3½) │",13,10
- DB " │ Capacidad límite física (82p) │ 1201.2 Kb │ 2002.0 Kb │ 4003.9 Kb │ │",13,10
- DB " └───────────────────────────────┴───────────┴───────────┴────────────┴──────┘",13,10
- DB " (#) Discos de 360K con formato /DH. (*) No probado. En la lista aparecen",13,10
- DB " SOLO los formatos soportados por casi todas las unidades y ordenadores.",13,10
- DB 10
- DB " Los disquetes 2MGUI utilizan una tecnología totalmente nueva, que permite",13,10
- DB " acceder directamente a la unidad, con una técnica ideada por Jesús Arias, sin",13,10
- DB " emplear -en la práctica- la controladora de disquetes. En escritura son más",13,10
- DB " lentos que un disco normal, pero leyendo lo superan. El consumo de memoria de",13,10
- DB " este programa (17 Kb en 1.44M) es elevado. Estos discos son casi tan seguros",13,10
- DB " como los 2M normales o los 2MF/M, pero su arquitectura no es la mejor de cara",13,10
- DB " a su empleo bajo sistemas multitarea. Funcionan en la mayoría de PC, XT y AT",13,10
- DB " con controladora y unidades de alta densidad.",13,10
- DB " (2/5) [PULSA UNA TECLA]",1
- DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8," ",13,10,10
- DB " ────────────────── OTRAS OPCIONES DEL PROGRAMA SON ───────────────────",13,10
- DB " /Q Hace un formateo rápido de las dos primeras pistas; útil para cambiar",13,10
- DB " las características lógicas de un disco no defectuoso ya formateado.",13,10
- DB " /L=et Establece la etiqueta de volúmen del disco (máximo 11 caracteres). Se",13,10
- DB " admiten mayúsculas y minúsculas.",13,10
- DB " /V=et Establece una etiqueta de volúmen incremental en series de discos (es",13,10
- DB " preciso que acabe en número).",13,10
- DB " /TEST Obtiene con exactitud total la capacidad admitida por la unidad que se",13,10
- DB " indique, y determina la velocidad de rotación de la misma. El disco no",13,10
- DB " necesita estar formateado y los datos que contuviera se pierden (test",13,10
- DB " destructivo). Puede acompañarse de /DD ó /ED para elegir densidad; por",13,10
- DB " defecto se realiza el test en alta densidad. También se admite /NODMA.",13,10
- DB " /B=n Fuerza el formateo con una determinada capacidad por pista (quizá la",13,10
- DB " obtenida por la prueba anterior). Así, se aprovechará totalmente la",13,10
- DB " capacidad de una unidad concreta. Estos disquetes podrán ser LEIDOS en",13,10
- DB " otras disqueteras, pero su ESCRITURA en unidades peores los dañará.",13,10
- DB " /G=n Selecciona el valor del GAP anti-FIFO. La capacidad bruta de la pista",13,10
- DB " es la suma de este valor (por defecto, 20) más el indicado con /B: un",13,10
- DB " menor GAP permite aumentar /B pero disminuye la seguridad.",13,10
- DB " /M=n Elige el número de pistas de alta densidad en el formato /DH (28 por",13,10
- DB " defecto, equivalentes a la primera tercera parte del disco).",13,10
- DB " /DRON Activa el soporte para DISKCOPY inverso (lo contrario es /DROFF). Use",13,10
- DB " solo /DRON o /DROFF si DISKCOPY recalibrara en cada pista. /DRON está",13,10
- DB " activo por defecto en DR-DOS 6 y Novell DOS 7.",13,10
- DB " (3/5) [PULSA UNA TECLA]",1
- DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8," ",13,10,10
- DB " /DWOFF Desactiva la caché de escritura retardada (lo contrario es /DWON). Por",13,10
- DB " defecto, la escritura retardada está activa. Inhíbala si detecta algún",13,10
- DB " conflicto con otro software de sistema, si bien sería muy raro. Copiar",13,10
- DB " discos (DISKCOPY) sin escritura retardada puede representar horas.",13,10
- DB " /X=n Valor para desplazar el comienzo físico de una pista respecto a la que",13,10
- DB " le precede, al conmutar de cabezal, expresado en grados (0-359°) de",13,10
- DB " longitud angular de la pista (sector sliding /X), por defecto 55°.",13,10
- DB " /Y=n Similar al anterior pero al conmutar de cilindro, por defecto 90°. No",13,10
- DB " altere /X ni /Y si no conoce su significado: incide en el rendimiento.",13,10
- DB " /NODMA Desactiva el funcionamiento en modo DMA. En modo DMA, QEMM necesita el",13,10
- DB " parámetro DMA=13 (1.44M) ó DMA=25 (2.88M), aunque EMM386 no. Se puede",13,10
- DB " evitar esto (o el cruce de una frontera de DMA) indicando esta opción:",13,10
- DB " 2MGUI permite operar en los AT sin DMA, aunque así es menos compatible",13,10
- DB " con ciertas configuraciones (cuando funciona, la seguridad es total).",13,10
- DB " /EMS Sólo admitido junto a /NODMA, utiliza EMS para consumir sólo 5 Kb.",13,10
- DB 10
- DB " Derechos de copia:",13,10
- DB " ──────────────────",13,10
- DB " La tecnología empleada por 2MGUI y el formato de disco resultante son dominio",13,10
- DB " público. Cualquier patente posterior de la técnica de acceso a pistas físicas",13,10
- DB " completas, realizada en cualquier país, carecerá de validez. Este programa,",13,10
- DB " sin embargo, sí es Copyright (C) de su autor. Puede ser libre y gratuitamente",13,10
- DB " distribuído; la condición de registro es la del paquete 2M (enviar la tarjeta",13,10
- DB " postal al autor).",13,10
- DB " (4/5) [PULSA UNA TECLA]",1
- DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8," ",13,10,10
- DB " Ultimas consideraciones:",13,10
- DB " ────────────────────────",13,10
- DB " - Se puede ejecutar DISKCOPY sobre una unidad 2MGUI, sobre cualquier tipo de",13,10
- DB " disco, siempre que el disco destino esté ya formateado, y tenga exactamente",13,10
- DB " las mismas características físicas y tamaño que el origen. El DISKCOPY del",13,10
- DB " MS-DOS (no del DR-DOS) falla en la primera ejecución sobre un nuevo disco",13,10
- DB " cuando no es del mismo tipo que el accedido por última vez; esto es porque",13,10
- DB " no soporta que un controlador de dispositivo modifique, dinámicamente, sus",13,10
- DB " características físicas. Si DISKCOPY da error, vuelva a ejecutarlo; en todo",13,10
- DB " caso, es mejor hacer antes un DIR sobre la unidad, para evitar problemas.",13,10
- DB 10
- DB " - 2MGUI realiza una escritura retardada (sólo en discos 2MGUI). El usuario no",13,10
- DB " debería retirar el disco, aunque haya aparecido ya el prompt del sistema,",13,10
- DB " hasta que haya transcurrido algo más de medio segundo.",13,10
- DB 10
- DB " Importante:",13,10
- DB " ───────────",13,10
- DB " - Bajo Windows 3 las operaciones sobre disquetes 2MGUI en el administrador de",13,10
- DB " archivos dejan colapsado el sistema. Sin embargo, aunque el puntero del",13,10
- DB " ratón no obedezca y el teclado parezca estar bloqueado, el sistema no está",13,10
- DB " necesariamente colgado. Espere unos segundos antes de resetear. Windows 95",13,10
- DB " es compatible con 2MGUI sólo en las sesiones de auténtico MS-DOS.",13,10
- DB " - Es conveniente indicar BUFFERS=40 en CONFIG.SYS para mayor rendimiento.",13,10
- DB 255
-
- DB 13,10,10
- DB " 2M GUINNESS 1.0 - DIRECT DISK DRIVE ACCESS BYPASSING CONTROLLER",13,10
- DB " (C) 1994-1995 Ciriaco García de Celis - Grupo Universitario de Informática.",13,10
- DB " C/Renedo, 2, 4-C; 47005 Valladolid (Spain) - ciri@gui.uva.es - 2:341/21.8",13,10
- DB 10
- DB " 2MGUI [U:] [/DD] [/DH] [/ED] [/T:n] [/R:n] [/C:n] [/S:n] [/F:n] [/N] [/K]",13,10
- DB 10
- DB " This program gets *all* disk's size available before format process; it is",13,10
- DB " also capable of fitting itself at disk drive speed in order to get more size.",13,10
- DB 10
- DB " You must load it first in CONFIG.SYS with a line like «DEVICE=2MGUI.EXE»;",13,10
- DB " from this moment, there will appear as many new disk drive letters as high",13,10
- DB " density drives installed on the system. New disks formatted by this program",13,10
- DB " only can be used on such new drives, which also support standard disks (and",13,10
- DB " even 2M disks if 2M is loaded). In fact, 2MGUI lets OS/2 support 2M disks in",13,10
- DB " these new drives. When changing from a new drive to the physical one or vice",13,10
- DB " versa, a disk change is simulated (user won't be asked for new disk).",13,10
- DB 10
- DB " To format new disks, you can execute 2MGUI useing the drive which supports",13,10
- DB " them. By default, high density is used; /DD selects double density, /DH makes",13,10
- DB " 1/3 in high density and 2/3 in double density (only 360K disks) and /ED means",13,10
- DB " 2.88M format; /T selects the number of tracks (80-86, 82 by default), /R the",13,10
- DB " minimum number of root files (1-240); /C the cluster size (128-16384) and /S",13,10
- DB " the sector size (128-512), both must be a power of 2; /F the FATs (1-2), /N",13,10
- DB " turns verify off and /K skips keyboard pauses.",13,10
- DB " (1/5) [PRESS ANY KEY]",1
- DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8," ",13,10,10
- DB " ┌───────────┬───────────┬────────────┐",13,10
- DB " │ Double │ High │ Extra high │",13,10
- DB " ┌───────────────────────────────┼───────────┼───────────┼────────────┼──────┐",13,10
- DB " │ Absolute record before 2M │ 820.0 Kb │ 1394.0 Kb │ -- │ │",13,10
- DB " │ Maximum 2M capacity (2MF /M) │ 902.0 Kb │ 1558.0 Kb │ -- │ 5.25 │",13,10
- DB " │ Minimum 2MGUI capacity │ 976.7 Kb │ 1639.8 Kb │ 1203.1 Kb# │ (5¼) │",13,10
- DB " │ Physical limit (82 tracks) │ 1001.0 Kb │ 1668.2 Kb │ 1228.8 Kb# │ │",13,10
- DB " ├───────────────────────────────┼───────────┼───────────┼────────────┼──────┤",13,10
- DB " │ Absolute record before 2M │ 984.0 Kb │ 1722.0 Kb │ 2880.0 Kb │ │",13,10
- DB " │ Maximum 2M capacity (2MF /M) │ 1066.0 Kb │ 1886.0 Kb │ 3772.0 Kb* │ 3.5 │",13,10
- DB " │ Minimum 2MGUI capacity │ 1176.0 Kb │ 1972.0 Kb │ 3944.0 Kb* │ (3½) │",13,10
- DB " │ Physical limit (82 tracks) │ 1201.2 Kb │ 2002.0 Kb │ 4003.9 Kb │ │",13,10
- DB " └───────────────────────────────┴───────────┴───────────┴────────────┴──────┘",13,10
- DB " (#) 360K diskettes with /DH format. (*) Not tested. Here are listed ONLY",13,10
- DB " those disk formats supported by most diskette drives and computer systems.",13,10
- DB 10
- DB " 2MGUI disks use a completely new technology to access a diskette drive",13,10
- DB " directly, with a technique discovered by Jesús Arias, bypasing in fact the",13,10
- DB " diskette drive controller. Writing is a little slower than a normal disk but",13,10
- DB " reading is faster. The memory spent by 2MGUI (usually, 17Kb in 1.44M) is a",13,10
- DB " little high. These disks are almost as reliable as 2M normal disks or 2MF/M",13,10
- DB " ones, but their design is not as suitable for use in real multitasking",13,10
- DB " environs. These diskette formats work on most PC, XT or AT computers with",13,10
- DB " high density drives and disk controllers.",13,10
- DB " (2/5) [PRESS ANY KEY]",1
- DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8," ",13,10,10
- DB " ──────────────────── OTHER SWITCHES SUPPORTED ARE ────────────────────",13,10
- DB " /Q Performs a quick format of two first tracks. Useful to change logical",13,10
- DB " characteristics of a full non-defective already 2mgui-formatted disk.",13,10
- DB " /L=lb Sets the volume label of the disk (maximum of 11 characters). It will",13,10
- DB " be accepted in either uppercase and lowercase.",13,10
- DB " /V=lb Sets an automatic sequencing of labels (the specified one must be",13,10
- DB " number terminated).",13,10
- DB " /TEST Evals, with high accuracy, the disk capacity supported by the selected",13,10
- DB " disk drive, and also measures the drive rotation speed. The test disk",13,10
- DB " doesn't need to be formatted and data stored will be lost (destructive",13,10
- DB " test). It can be used with /DD or /ED switches to select disk density;",13,10
- DB " by default, high density will be used. Also /NODMA can be selected.",13,10
- DB " /B=n Forzes a new track size (perhaps the maximum track size reported by",13,10
- DB " the previous disk test). So, you can employ all disk capacity of your",13,10
- DB " own drive. These disks can be READ without problem on any other disk",13,10
- DB " drives, but WRITING them in poorer drives will damage data stored.",13,10
- DB " /G=n Selects the anti-FIFO gap value. The crude track size is the addition",13,10
- DB " of this value (by default, 20) and the size set with /B: a smaller GAP",13,10
- DB " lets you to increment /B but decreases disk reliability.",13,10
- DB " /M=n Sets the number of high density tracks in /DH format (by default, 28;",13,10
- DB " which means the first third part of the disk).",13,10
- DB " /DRON Turns on inverse DISKCOPY support (the opposite is /DROFF). Only must",13,10
- DB " be used /DRON or /DROFF if DISKCOPY recalibrates on each track. /DRON",13,10
- DB " is set by default in DR-DOS 6 and Novell DOS 7.",13,10
- DB " (3/5) [PRESS ANY KEY]",1
- DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8," ",13,10,10
- DB " /DWOFF Disables delayed-write cache (the opposite is /DWON). By default, the",13,10
- DB " delayed write is active. You can turn it off if you detect a conflict",13,10
- DB " with any other system software, but this is really unusual. To copy",13,10
- DB " disks (DISKCOPY) without delayed write may take hours.",13,10
- DB " /X=n Value to shift the beginning of a track from the previous one, when",13,10
- DB " changing the head selected shown in degrees (0-359°) of angular length",13,10
- DB " of the track (sector sliding /X), 55° by default.",13,10
- DB " /Y=n Similar to previous switch, but when changing the cylinder (90°). Do",13,10
- DB " not modify /X or /Y without knowing how: they alter disk performance.",13,10
- DB " /NODMA Turns off DMA mode. In DMA mode, QEMM needs a DMA=13 (1.44M) or DMA=25",13,10
- DB " (2.88M) switch, but EMM386 does not need it. You can avoid this (or a",13,10
- DB " DMA frontier crossing problem) with this option: 2MGUI can work in AT",13,10
- DB " systems without using DMA; but in this way, it is less compatible with",13,10
- DB " some system configurations (but if works, the reliability is similar).",13,10
- DB " /EMS Only allowed with /NODMA, saves memory (uses 5 Kb) using EMS instead.",13,10
- DB 10
- DB " Copyright:",13,10
- DB " ──────────",13,10
- DB " The technology used by 2MGUI and the resulting disk format are, both, public",13,10
- DB " domain. Any patent registered in any country with the technique of access to",13,10
- DB " complete tracks will be void. This program, however, is Copyright (C) of its",13,10
- DB " author. It can be freely and without charge distributed; the condition to be",13,10
- DB " a registered user is the same that with 2M package (to send a postcard to the",13,10
- DB " author).",13,10
- DB " (4/5) [PRESS ANY KEY]",1
- DB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8," ",13,10,10
- DB " Some finally notes:",13,10
- DB " ───────────────────",13,10
- DB " - It is possible to run DISKCOPY into a 2MGUI drive, over any one disk format",13,10
- DB " available, but target diskette must be already formatted, and must be of",13,10
- DB " the same physical characteristics and size as source one. MS-DOS DISKCOPY",13,10
- DB " (not DR-DOS one) fails on first execution over a new disk, when it is not",13,10
- DB " of the same type as the latest accessed the last time; the problem occurs",13,10
- DB " because DISKCOPY doesn't support that a device drive modifies, on the fly,",13,10
- DB " it physical characteristics. If DISKCOPY returns an error execute it again;",13,10
- DB " but it's preferable to perform a DIR command over the drive before copying.",13,10
- DB 10
- DB " - 2MGUI performs a delayed-write on diskette drives (speeding up only 2MGUI",13,10
- DB " diskettes). The user must not extract the disk although system prompt has",13,10
- DB " already returned, until after at least a half second and a little more.",13,10
- DB 10
- DB " Important:",13,10
- DB " ──────────",13,10
- DB " - Under Windows 3, operations performed on 2MGUI disks under file manager may",13,10
- DB " appear to hang the system. However, although mouse pointer does not answer",13,10
- DB " and keyboard seems to be locked, the system has not necessarily crashed.",13,10
- DB " Wait for some seconds before resetting it. Windows 95 is compatible with",13,10
- DB " 2MGUI only in true MS-DOS sessions.",13,10
- DB " - It is recommended to set BUFFERS=40 in CONFIG.SYS to improve performance.",13,10
- DB 0
-
- buffer_aux DB 256 DUP (0) ; buffer para alguna función del DOS/EMS
-
- _PRINCIPAL ENDS
-
- tampila EQU 2048 ; 2 Kb de pila son suficientes
-
- _PILA SEGMENT STACK 'STACK'
- DB tampila DUP (?)
- _PILA ENDS
-
- END main
-